HarmonyOS 鸿蒙Next中Promise reject之后,Promise中的代码还在运行

HarmonyOS 鸿蒙Next中Promise reject之后,Promise中的代码还在运行

由于想在组件的aboutToDisappear中取消正在执行的Promise避免资源的浪费

cancelPromise: () => void = () => {}

aboutToAppear(): void {
  new Promise<string>(async (resolve, reject) => {
    this.cancelPromise = () => {
      reject({ code: -1, message: "cancel promise" } as BusinessError<undefined>);
    }

    let i = 0
    while (i < 1000) {
      i++
      await sleep(100)
      Logger.debug(i.toString())
    }
    resolve(i.toString())
  }).then((str) => {
    Logger.info(str)
  }).catch((e: BusinessError) => {
    Logger.error(e.message)
  })
}

aboutToDisappear(): void {
  this.cancelPromise()
}

结果发现退出该页面后, Promise中的while代码还在执行!

引入一个标志位来判断:

new Promise<string>(async (resolve, reject) => {
    let isPending = true
    this.cancelPromise = () => {
      reject({ code: -1, message: "cancel promise" } as BusinessError<undefined>);
      isPending = false
    }

    let i = 0
    while (i < 1000 && isPending) {
      i++
      await sleep(100)
      Logger.debug(i.toString())
    }
    resolve(i.toString())
  }).then((str) => {
    Logger.info(str)
  }).catch((e: BusinessError) => {
    Logger.error(e.message)
  })

ok退出页面后,Promise中的代码没在执行了。

那如果Promise执行的是一个http请求呢?http还没有响应就退出该页面,那该如何去取消这个promise?

封装一个createCancellablePromise方法,ts代码:

export function createCancellablePromise<T>(executor: ((resolve: (value: T | PromiseLike<T>) => void, reject: (reason?: any) => void,eventId:string,isPending:() =>boolean) => void):  Promise<T>{
  let _resolve: any = null;
  let _reject: any = null;

  // 创建 Promise 并绑定事件监听
  return new Promise<T>((resolve, reject) => {
    const eventId: string = util.generateRandomUUID(true);
    let pending = true
    const isPending = () => {return pending}
    // 注册一次性事件监听
    emitter.once(eventId, () => {
      reject({code:-1,message:"cancel promise"} as BusinessError<undefined>);
      pending = false
    });

    _resolve = (value: T) => {
      emitter.off(eventId)
      resolve(value);
      pending = false
    };

    _reject = (reason?: any) => {
      emitter.off(eventId)
      reject(reason);
      pending = false
    };

    // 执行主任务
    executor(_resolve, _reject,eventId,isPending);
  });
}

组件页面代码:

cancelPromise: () => void = () => {}

async rcpGetRepositories(cancelEventId: string): Promise<Repositories> {
  const req =
    new rcp.Request(`https://api.github.com/search/repositories?q=node.js+language:javascript&sort=stars`, 'GET')
  //收到取消promise的事件,则取消指定或正在进行的会话请求
  emitter.once(cancelEventId, () => {
    session.cancel(req)
  })
  let response = await session.fetch(req)
  if (response.statusCode == 200 && response.toJSON()) {
    return response.toJSON() as Repositories
  } else {
    return Promise.reject({ code: -2, message: "response is undefined" } as BusinessError<undefined>);
  }
}

aboutToAppear(): void {
  createCancellablePromise<Repositories>(async (resolve, reject, cancelEventId, isPending) => {
    this.cancelPromise = () => {
      if (isPending()) {
        emitter.emit(cancelEventId)
      }
    }
    //http请求数据
    this.rcpGetRepositories(cancelEventId).then((rep) => {
      Logger.info(`rcpGetRepositories then ${rep}`)
      resolve(rep)
    }).catch((e: BusinessError) => {
      Logger.error(`rcpGetRepositories catch ${e.message}`)
      reject(e)
    })

  }).then((repositories) => {
    this.repositories = repositories
  }).catch((e: BusinessError) => {
    Logger.error(e.message)
  })
}

aboutToDisappear(): void {
  this.cancelPromise()
}

更多关于HarmonyOS 鸿蒙Next中Promise reject之后,Promise中的代码还在运行的实战教程也可以访问 https://www.itying.com/category-93-b0.html

2 回复

在HarmonyOS鸿蒙Next中,当Promise被reject后,Promise内的代码仍会继续执行直到完成。这是由于Promise的执行机制决定的,reject仅改变Promise状态并触发catch回调,但不会中断已开始执行的代码。要停止后续执行,需要在reject后手动添加return或通过条件判断终止逻辑。示例:

new Promise((resolve, reject) => {
  reject('error');
  console.log('这行仍会执行'); 
  // 需自行终止
  return; 
}).catch(err => {});

更多关于HarmonyOS 鸿蒙Next中Promise reject之后,Promise中的代码还在运行的实战系列教程也可以访问 https://www.itying.com/category-93-b0.html


这是一个关于Promise取消机制在HarmonyOS中的实现问题。根据代码分析,您已经正确理解了Promise的基本行为:调用reject()并不会中断正在执行的Promise代码,只是改变了Promise的状态。

对于HTTP请求的取消,您的解决方案是正确的。关键点在于:

  1. 使用session.cancel()来真正终止网络请求
  2. 通过事件机制(emitter)来触发取消操作
  3. 使用isPending标志位来避免不必要的取消操作

这种实现方式符合Promise的设计原则,因为:

  • 原生Promise没有内置取消机制
  • 需要开发者自行实现取消逻辑
  • 网络请求需要调用特定API(session.cancel)才能真正终止

您的createCancellablePromise封装很好地解决了这个问题,这种模式在HarmonyOS开发中是推荐的实践方式。

对于其他异步操作,也可以采用类似的模式:在取消时不仅调用reject,还要调用具体的终止API(如网络请求的cancel、定时器的clear等)。

回到顶部