12 javascript asynchronous promise
已经发布了很多关于 async/await 在 javascript map 函数中的行为的主题,但是,下面两个示例中的详细说明会很好:
  const resultsPromises = myArray.map(async number => {
    return await getResult(number);
  });
  const resultsPromises = myArray.map(number => {
    return getResult(number);
  });
编辑:这当然是一个虚构的案例,所以刚刚开始辩论,为什么,如何以及何时映射函数等待 await 关键字。解决方案如何修改这个例子,调用 Promise.all() 不是这个问题的目的。
getResult是一个异步函数
Sco*_*ger 13
其他答案已经很好地涵盖了您的示例行为的细节,但我想尝试更简洁地说明它。
const resultsPromises = myArray.map(async number => {
  return await getResult(number);
});
const resultsPromises = myArray.map(number => {
  return getResult(number);
});
Array.prototype.map 同步循环遍历数组并将每个元素转换为其回调的返回值。
两个示例都返回 aPromise。
async函数总是返回 a Promise。
getResult返回一个Promise.
因此,如果没有错误,您可以在伪代码中将它们视为:
const resultsPromises = myArray.map(/* map each element to a Promise */);
正如zero298 所说和alnitak 所证明的那样,这非常快速(同步)按顺序启动每个承诺;但是,由于它们是并行运行的,因此每个 promise 都会按照他们认为合适的方式解决/拒绝,并且可能不会按顺序解决(履行或拒绝)。
并行运行 promise 并Promise.all使用for * 循环或Array.prototype.reduce.
或者,您可以将第三方模块用于我维护的可链接异步 JavaScript 方法来清理内容,并且——也许——使代码符合您对异步映射操作可能如何工作的直觉:
const delay = ms => new Promise(resolve => setTimeout(resolve, ms));
const getResult = async n => {
  await delay(Math.random() * 1000);
  console.log(n);
  return n;
};
(async () => {
  console.log('parallel:');
  await AsyncAF([1, 2, 3]).map(getResult).then(console.log);
  
  console.log('sequential:');
  await AsyncAF([1, 2, 3]).series.map(getResult).then(console.log)
})();<script src="https://unpkg.com/async-af@7.0.12/index.js"></script>Array.prototype.map()是一个转换数组的函数。它将一个数组映射到另一个数组。其函数签名中最重要的部分是回调。对 Array 中的每个项目调用回调,回调返回的是放入由 返回的新 Array 中的内容map。
它对返回的内容没有任何特别之处。它不调用.then()项目,它不做await任何事情。它同步转换数据。
这意味着如果回调返回 a Promise(所有async函数都会这样做),所有的 promise 都将是“热的”并并行运行。
在您的示例中,如果getResult()返回 aPromise或本身是异步的,则您的实现之间没有真正的区别。  resultsPromises将由Promise可能尚未解决的s填充。
如果您想在继续之前等待一切完成,则需要使用Promise.all().
此外,如果您只想getResults()一次运行1 ,请使用常规for循环并await在循环内进行。
async/await当你想通过删除.then()回调来扁平化你的代码或者你想隐式返回一个 Promise时,它很有用:
const delay = n => new Promise(res => setTimeout(res, n));
async function test1() {
  await delay(200);
  // do something usefull here
  console.log('hello 1');
}
async function test2() {
  return 'hello 2'; // this returned value will be wrapped in a Promise
}
test1();
test2().then(console.log);但是,在您的情况下,您没有使用await替换 a .then(),也没有使用它来返回隐式承诺,因为您的函数已经返回了一个承诺。所以它们不是必需的。
如果您想并行运行所有 Promise,我建议简单地返回getResultwith的结果map()并生成一个 Promise 数组。Promise 将按顺序启动,但最终会并行运行。
const resultsPromises = indicators.map(getResult);
然后您可以等待所有承诺并使用Promise.all()以下方法获得已解决的结果:
const resultsPromises = indicators.map(getResult);
但是,如果您想按顺序运行每个 Promise 并在运行下一个 Promise 之前等待前一个 Promise 解决,那么您可以使用reduce()并async/await像这样:
const data = [1, 2, 3];
const getResult = x => new Promise(res => {
  return setTimeout(() => {
    console.log(x);
    res(x);
  }, Math.random() * 1000)
});
Promise.all(data.map(getResult)).then(console.log);如果第一个代码片段的目的是.map调用在返回之前等待所有 Promise 得到解决(并让这些回调按顺序运行),恐怕它不会像那样工作。该.map函数不知道如何使用async函数来做到这一点。
这可以用以下代码演示:
const array = [ 1, 2, 3, 4, 5 ];
      
function getResult(n)
{
    console.log('starting ' + n);
    return new Promise(resolve => {
        setTimeout(() => {
            console.log('finished ' + n);
            resolve(n);
        }, 1000 * (Math.random(5) + 1));
    });
}
let promises = array.map(async (n) => {
    return await getResult(n);
});
console.log('map finished');
Promise.all(promises).then(console.log);您将看到.map调用在任何异步操作完成之前立即完成。
| 归档时间: | 
 | 
| 查看次数: | 17624 次 | 
| 最近记录: |