如何在javascript中同步异步映射函数 [英] How to synchronize an async map function in javascript

查看:79
本文介绍了如何在javascript中同步异步映射函数的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个异步映射函数,但希望它同步执行,因为我需要在同一循环中使用第一条语句的输出.但是,即使使用await语句,地图也可以异步运行,请您帮忙了解为什么会发生这种情况.

I have a async map function but want it to execute synchronously because I need the output of the first statement to be used within the same loop. But the map runs asynchronously even with await statements, can you please help understand why this happens.

我的用例是,如果不存在,则将记录插入mongodb;如果存在循环,则对其进行更新.数据存在于db中,但在循环中查找失败,但在外部可用.

My use case if to insert a record into mongodb if not present and update it if present in a loop. The data exists in the db but find fails within the loop but works outside.

我的代码:

        const doSomethingAsync = () => {
            return new Promise(resolve => {
                setTimeout(() => {
                    resolve(Date.now());
                }, 1000);
            });
        };

        await Promise.all(
            modelVarients.map(async varient => {
                console.log(`varient: ${varient._id}`);
                console.log('1');
                const onlineDevice = await Device.findOne({
                    model: varient._id,
                });
                console.log('2');
                await doSomethingAsync();
                console.log('3');
                await doSomethingAsync();
                console.log(JSON.stringify(onlineDevice));
                await doSomethingAsync();
                console.log('4');
                return varient;
            })
        );

我得到的日志:

varient: 8 pro
1
varient: note
1
varient: iphone x
1
2
2
2
3
3
3
null
null
null
4
4
4

但是我期望得到什么:

varient: 8 pro
1
2
3
<actual response from db for 8 pro>
4
varient: note
1
2
3
<actual response from db for note>
4
varient: iphone x
1
2
3
<actual response from db for iphone x>
4

推荐答案

modelVarients.map(async()=>> ...)将所有元素转换为Promises,这意味着他们都开始执行.然后 Promise.all()收集它们并等待所有它们,这就是为什么您可以使用此结构来等待 map 完成的原因.这是并行处理.

The modelVarients.map(async () => >...) converts all the elements into Promises, which means they all start executing. Then the Promise.all() collects them and waits for all of them, that's why you can use this structure to wait for the map to finish. This is parallel processing.

您需要的是顺序处理,您可以使用 reduce 进行处理,如下所示:

What you need is sequential processing, which you can do with a reduce, like this:

await modelVarients.reduce(async (memo, varient) => {
    await memo;
    // all the other things
}, Promise.resolve())

reduce map 类似,在某种意义上说,它为数组中的所有元素创建了Promise,但是有一个当前值从一个元素传递到另一个元素.在这种情况下,第一个是 Promise.resolve(),第二个是第一个的结果,依此类推.使用等待备忘录,您可以等待上一个结果.

reduce is similar to map in a sense that it creates a Promise for all the elements in the array, but there is a current value that is passed from one element to the other. In this case, it is the Promise.resolve() for the first one, the result of the first for the second, and so on. With the await memo you can wait for the previous result.

使用 reduce ,最后一个元素将等待上一个元素,然后等待上一个元素,依此类推,因此不需要Promise.all.

With reduce, the last element will wait for the previous one, which waits for the previous one, and so on, so there is no need for a Promise.all.

我写了有关地图减少与异步功能配合使用,它们将帮助您查看全局.

I've written articles about how map and reduce works with async functions, they will help you see the big picture.

这篇关于如何在javascript中同步异步映射函数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆