【问题标题】:Is using an async function inside Array.map synchronous在 Array.map 同步中使用异步函数
【发布时间】:2020-10-02 16:59:15
【问题描述】:

processImage() 是一个异步处理图像的函数。

uploadImage()是一个异步上传图片的函数。

它们都返回 Promise。

sizes 是长度为 4 的数组。

图片应在处理完毕后上传。单一尺寸的上传和处理不能同时进行。

我想要做的是一个接一个地立即启动所有 4 个处理/上传作业,并让它们一起异步执行。 4 个都完成后,我执行一些其他代码。

由于我将异步函数作为参数传递给映射,其中的await 关键字是否会暂停执行,直到第一张图像的处理/上传完成?在这种情况下,这将成为同步执行。我不明白这里到底发生了什么。如果这段代码确实是同步的,我该如何让它异步呢?

var responses = await Promise.all(sizes.map(async function (size) {
        let processedBuffer = await processImage(buffer, size);
        let response = await uploadImage(processedBuffer.toString('base64'));
        return response;
    }));

//some other code

【问题讨论】:

    标签: javascript async-await es6-promise


    【解决方案1】:

    您的代码是异步的。您可以轻松地自行检查。

    const mockAsyncFn = () =>
        new Promise(resolve => setTimeout(() => resolve(), 2000));
    
    const someAsync = async () => {
        const from = new Date();
        await Promise.all(
            [mockAsyncFn, mockAsyncFn].map(async fn => await fn())
        );
        const to = new Date();
        return to - from;
    };
    
    (async () => console.log(await someAsync()))();
    

    结果将是 ~2s 但不是 4。

    【讨论】:

    • 谢谢。我执行了这个 sn-p 并推断它确实是异步的。你能解释一下为什么会这样吗?为什么第二个 mockAsync() 函数不等待第一个完成?
    • Promise.all 运行异步函数数组并等待它们全部解决或其中一个被拒绝。
    【解决方案2】:

    async 是返回承诺的函数的语法糖。

    考虑这个简单的例子:

    async function ret42() {
       return 42;
    }
    

    这相当于:

    function ret42() {
       return Promise.resolve(42);
    }
    

    根据这种观点,回调中的异步函数是同步的,直到遇到await(这是.then(() => 的语法糖)。

    如果你想让每个函数都到达末尾以便执行下一个函数,你必须使用for await,或者只是:

    for (const fn of sizes) {
      await fn();
    }
    

    【讨论】:

      猜你喜欢
      • 2016-08-20
      • 2012-07-25
      • 1970-01-01
      • 2013-12-25
      • 1970-01-01
      • 2013-07-12
      • 2020-12-20
      • 1970-01-01
      • 2015-03-19
      相关资源
      最近更新 更多