为什么.then在异步函数中不执行上一个.then之后执行?

时间:2019-02-03 22:06:08

标签: javascript node.js es6-promise

多次调用_dispatch有时会导致同时传递给_dispatch的承诺。不是.then应该在之前的.then之后执行吗?

// Failing code
async _dispatch (promise) {
  // this._mutex is a Promise
  this._mutex = this._mutex.then(() => promise)
  return Promise.resolve(this._mutex)
}

// Possibly working code
async _dispatch (promise) {
  console.log('START_CS', promise)
  while (Atomics.load(this.done, 0) === 0) {
    await this.sleep(50)
  }
  Atomics.store(this.done, 0, 0)
  console.log('IN_CS', promise)
  const ret = await promise
  Atomics.store(this.done, 0, 1)
  console.log('END_CS', promise)
  return ret
}

_dispatch的使用方式如下:

async getStatus (ports) {
  const request = // ...
  return this._dispatch(someAsyncFunctionReturningArray(request, ports))
}
const polling = () => {
  const sleep = new Promise(resolve => setTimeout(resolve, 500))
  const status = this.getStatus().then(() => {}).catch(() => {})
  return Promise.all([sleep, status])
    .then(polling)
}
polling()

polling()和另一个类似的代码块正在同时运行。我注意到someAsyncFunctionReturningArray被同时调用。

2 个答案:

答案 0 :(得分:1)

Promise携带有关任务状态的信息,并允许您对状态进行操作。通常,它们本身并不代表任务。这相当于您正在做的事情:

async function foo() {
    console.log('foo() task ran');
}

function delay() {
    return new Promise(resolve => {
        setTimeout(resolve, 1000);
    });
}

const promise = foo();

delay().then(() => promise)

这不会延迟promise一秒钟,因为promise只是一个可以说“用值X解析”,“被错误Y拒绝”或“待处理”的对象。 。没有延迟承诺的概念-您延迟任务。该工作由foo完成,并在您致电foo()时开始。

目前尚不清楚您要提出的问题是正确的替代方法。我想这就是你要去的地方

_dispatch (action) {
  this._mutex = this._mutex.then(() => action())
  return this._mutex
}
async getStatus (ports) {
  const request = // ...
  return this._dispatch(() => someAsyncFunctionReturningArray(request, ports))
}

,但是可能有一种完全不同的方法会更有效,并且我们需要更多有关您要使用此队列来完成的工作的详细信息,以推荐一个方法。

答案 1 :(得分:0)

一个Promise并不是一个生成值的任务,而是一个需要花费一段时间的任务立即返回的值,然后才将结果传递出去。通过将它们链接在一起,将一个许诺添加到另一个许诺中不会影响任务的执行。但是,当承诺解决时,可以调用回调,例如:

async _dispatch(callback) {
 this._mutex = this._mutex.then(() => callback());
 return this._mutex;
}

然后可以用作:

 const getStatus = (ports) => this.dispatch(() => {
   const request = // ...
   return someAsyncFunctionReturningArray(request, ports);
 });

const sleep = new Promise(resolve => setTimeout(resolve, 500))

const polling = () => {
  const status = this.getStatus().then(() => {}).catch(() => {})
  return Promise.all([sleep, status])
   .then(polling)
};

polling();