【问题标题】:Why does async array map return promises, instead of values为什么异步数组映射返回承诺而不是值
【发布时间】:2017-11-29 16:10:13
【问题描述】:

请看下面的代码

var arr = await [1,2,3,4,5].map(async (index) => { 
    return await new Promise((resolve, reject) => {
        setTimeout(() => {
            resolve(index);
            console.log(index);
        }, 1000);
    });
});
console.log(arr); // <-- [Promise, Promise, Promise ....]
// i would expect it to return [1,2,3,4,5]

快速编辑: 公认的答案是正确的,因为 map 对异步函数没有做任何特殊的事情。我不知道为什么我认为它可以识别异步 fn 并且知道等待响应。

也许我期待这样的事情。

Array.prototype.mapAsync = async function(callback) {
    arr = [];
    for (var i = 0; i < this.length; i++)
        arr.push(await callback(this[i], i, this));
    return arr;
};

var arr = await [1,2,3,4,5].mapAsync(async (index) => { 
    return await new Promise((resolve, reject) => {
        setTimeout(() => {
            resolve(index);
            console.log(index);
        }, 1000);
    });
});
// outputs 1, 2 ,3 ... with 1 second intervals, 
// arr is [1,2,3,4,5] after 5 seconds.

【问题讨论】:

  • 当您清楚地为每个值返回新的Promise 时,为什么会期望有任何不同

标签: javascript promise async-await


【解决方案1】:

因为async 函数总是返回一个承诺;而map 没有异步的概念,也没有对 Promise 的特殊处理。

但是您可以通过Promise.all 轻松等待结果:

try {
    const results = await Promise.all(arr);
    // Use `results`, which will be an array
} catch (e) {
    // Handle error
}

现场示例:

var arr = [1,2,3,4,5].map(async (index) => { 
    return await new Promise((resolve, reject) => {
        setTimeout(() => {
            resolve(index);
            console.log(index);
        }, 1000);
    });
});
(async() => {
    try {
        console.log(await Promise.all(arr));
        // Use `results`, which will be an array
    } catch (e) {
        // Handle error
    }
})();
.as-console-wrapper {
  max-height: 100% !important;
}

或使用 Promise 语法

Promise.all(arr)
    .then(results => {
        // Use `results`, which will be an array
    })
    .catch(err => {
        // Handle error
    });

现场示例:

var arr = [1,2,3,4,5].map(async (index) => { 
    return await new Promise((resolve, reject) => {
        setTimeout(() => {
            resolve(index);
            console.log(index);
        }, 1000);
    });
});
Promise.all(arr)
    .then(results => {
        console.log(results);
    })
    .catch(err => {
        // Handle error
    });
.as-console-wrapper {
  max-height: 100% !important;
}

旁注:由于async 函数总是返回承诺,而你在函数中的唯一awaiting 是你创建的承诺,无论如何在这里使用async 函数是没有意义的.只需返回您正在创建的承诺:

var arr = [1,2,3,4,5].map((index) => { 
    return new Promise((resolve, reject) => {
        setTimeout(() => {
            resolve(index);
            console.log(index);
        }, 1000);
    });
});

当然,如果你真的在那里做一些更有趣的事情,awaits 处理各种事情(而不仅仅是new Promise(...)),那就不同了。 :-)

【讨论】:

    【解决方案2】:

    由于它是异步的,所以在map 返回时尚未确定值。在箭头函数运行之前,它们不会存在。

    这就是 Promise 存在的原因。它们是对未来可用价值的承诺。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2018-12-22
      相关资源
      最近更新 更多