在解决它之前等待Promise.all内的Promise完成

时间:2017-04-13 21:05:27

标签: javascript promise es6-promise

我有一个Promise.all,它执行映射在数组输入上的异步函数,如果它不是null,然后将数据解析为先前定义的Promise:

Promise.all((inputs || []).map(input => {
  return new Promise((resolve, reject) => {
    someAsyncFunc(input)
    .then(intermediateOutput => {
      someOtherAsyncFunc(intermediateOutput )
      .then(output => {
        return Promise.resolve(output )
      })
      .catch(reason=> {
        return Promise.reject(reason)
      })
    })
    .catch(reason => {
      return Promise.reject(reason);
    })
  })
  .then(outputs => {
    resolve(outputs)
  })
  .catch(reason => {
    reject(reason)
  })
}))

即使someAsyncFunc完成其工作,我也只获得空输出。如何让Promise.all等待内部的承诺完成异步工作?

2 个答案:

答案 0 :(得分:3)

不仅仅是

return Promise.all((inputs || []).map(input =>
 somePromiseFunc(input).then(someOtherPromiseFunc)
);

工作?

您第一次没有使用Promise.all,因为它将一组承诺作为输入,而不是(resolve, reject) => { ... }

一旦潜在的承诺失败,

Promise.all就会被拒绝,所以你不需要尝试围绕catch(error => reject(error)做一些事情

示例:

const somePromiseFunc = (input) => new Promise((resolve, reject) => {
  setTimeout(() => {
    if (input === 0) { reject(new Error('input is 0')); }
    resolve(input + 1);
  }, 1000);
});

const someOtherPromiseFunc = (intermediateOutput) => new Promise((resolve, reject) => {
  setTimeout(() => {
    if (intermediateOutput === 0) { reject(new Error('intermediateOutput is 0')); }
    resolve(intermediateOutput + 1);
  }, 1000);
});

const f = inputs => {
  const t0 = Date.now()
  return Promise.all((inputs || []).map(input => somePromiseFunc(input).then(someOtherPromiseFunc)))
    .then(res => console.log(`result: ${JSON.stringify(res)} (after ${Date.now() - t0}ms)`))
    .catch(e => console.log(`error: ${e} (after ${Date.now() - t0}ms)`));
};

f(null)
// result: [] (after 0ms)

f([1, 0])
// error: Error: input is 0 (after 1001ms)

f([1, -1])
// error: Error: intermediateOutput is 0 (after 2002ms)

f([1, 2])
// result: [3,4] (after 2002ms)

答案 1 :(得分:2)

请参阅jfriend的评论。

someAsyncFuncsomeOtherAsyncFunc是正确返回承诺的函数 像return new Promise(/*...*/);

这样的东西

这没用:

.then(output => {
  return Promise.resolve(output )
})

阅读Promise文档

相同

.catch(reason=> {
  return Promise.reject(reason)
})

承诺已经拒绝,你不需要抓住并拒绝自己

确保Promise是可链接的,你需要返回Promise

// ...
return new Promise((resolve, reject) => {
  if(inputs == null)
    resolve([]);
  else {
    Promise.all(inputs.map(input => {
      return someAsyncFunc(input)
        .then(someOtherAsyncFunc)
    }))
      .then(resolve)
      .catch(reject)
  }
});

请注意,我宁愿不为Promise.all内联制作arry,它会增加视觉上的混乱:

return new Promise((resolve, reject) => {
  if(inputs == null)
    resolve([]);
  else {
    const myPromises = inputs.map(input => {
      return someAsyncFunc(input)
        .then(someOtherAsyncFunc)
    });
    Promise.all(myPromises)
      .then(resolve)
      .catch(reject)
  }
});
如果你犯了其他错误,它可能仍会失败。