为什么异步数组映射返回的是 Promise 而不是值?

5
请见下方代码:
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对异步函数没有任何特殊处理。我不知道为什么我会认为它能识别异步函数并等待响应。
我原本期望的是这样的。
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时,你为什么会期望有任何不同呢? - musefan
2个回答

14
由于async函数总是返回一个promise;而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函数总是返回promise,而你在函数中唯一需要await的是你创建的promise,所以在这里使用async函数是没有意义的。只需返回你创建的promise:

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

当然,如果你在那里做更有趣的事情,涉及到各种 await(而不仅仅是在 new Promise(...) 上),那就是不同的了。 :-)


0

由于它是异步的,因此在map返回时,值尚未确定。直到箭头函数运行后,它们才会存在。

这就是为什么Promise存在的原因。它们是将来可用值的承诺。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接