首页 > 解决方案 > 如何与 forEach 同时执行承诺?

问题描述

我有一个代码可以在我的系统中更新或创建新用户。它与 forEach 函数一起使用,效果很好。但是,我想利用 Node.js 并同时执行多个更新/创建。我试图创建一系列承诺,但我认为我构建的承诺是错误的。这是可以正常工作的代码:

import usersjson from './jsons/users.json';
if (usersjson.users.length) {
    for (const user of usersjson.users) {
        let getuser = getUser(url, user.Id, 'Id');
            getuser.then((data) => {//Make a call to get user by id
                if (data.users.length != 0) { //If user exists
                    let update = updateUser(url, user, data.users[0].id);//update user function
                    update.then((updateresponse) => {
                        console.log(updateresponse);
                        }).catch((err) => {
                            console.log(err);
                        })
                } else { //if user doesn't exist
                    let update = newUser(url, user);//createUser(settings.fieldMap, user)
                    update.then((response) => {
                        console.log(response);
                    }).catch((err) => {
                        console.log(err);
                    });
                }
            }) 
    };
};

现在,我想将“更新”变成 Promise,这样我就可以使用 Promise.all() 同时发送多个。这是我尝试过的:

import usersjson from './jsons/users.json';
let promises = [];
if (usersjson.users.length) {
    for (const user of usersjson.users) {
        if (promises.length <= 20) {
            let getuser = getUser(url, user.Id, 'Id');
            getuser.then((data) => {//Make a call to get user by id
                if (data.users.length != 0) { //If user exists
                    let update = new promise ((resolve, reject) => {
                        updateUser(url, user, data.users[0].id).then((response) => {
                            resolve(response);
                        }).catch((err) => {
                            console.log(err)
                        });
                    });
                    promises.push(update);
                } else { //if user doesn't exist
                    let update = new promise ((resolve, reject) => {
                        newUser(url, user).then((response) => {
                            resolve(response);
                        }).catch((err) => {
                            console.log(err);
                        })
                    });
                    psomises.push(update);
                }
            });
        } else {
            await promises.all(update)
            .then ((result) => {
                console.log(result);
                promises = [];
            }).catch(err){
                console.log(err);
            }
        };
    };
};

但我收到一条错误消息:

(node:22016) UnhandledPromiseRejectionWarning: ReferenceError: promise is not defined at file:///C:/xampp/htdocs/NodeAPI/server.js:70:21 at processTicksAndRejections (internal/process/task_queues.js:97:5) (节点:22016) UnhandledPromiseRejectionWarning:未处理的承诺拒绝。此错误源于在没有 catch 块的情况下抛出异步函数内部,或拒绝未使用 .catch() 处理的承诺。要在未处理的 Promise 拒绝时终止节点进程,请使用 CLI 标志--unhandled-rejections=strict(请参阅 https://nodejs.org/api/cli.html#cli_unhandled_rejections_mode)。(拒绝 ID:1)(节点:22016)[DEP0018] DeprecationWarning:不推荐使用未处理的承诺拒绝。将来,未处理的 Promise 拒绝将使用非零退出代码终止 Node.js 进程。

我的问题是,如何让数组中的 20 个用户同时运行 forEach,而不是一个一个地运行?

标签: node.jsarraysforeachpromise

解决方案


  1. 首先,将处理每个单独值的代码流user移动到它自己的单独async函数中。

    • 由于async函数的实际工作方式(因为每个函数都标记了每个异步状态机的边界),在语句async function中执行并发异步工作实际上并不可行。for
  2. for循环中调用该函数。

  3. 总是更===喜欢==

  4. 使用打字稿。在没有 TypeScript 的情况下使用asyncJavaScript 是一个痛苦的世界,因为您需要跟踪哪些函数返回Promise<T>与哪些不返回,以及正确解包Promise<T>对象。

  5. 只要有可能,总是有你自己的try/catch语句来包装函数的整个主体async,否则你将不得不处理不同的 JS 引擎和 JS 代码如何处理抛出的异常和对象的不一致。

import usersjson from './jsons/users.json';

async function updateUsers() {
    
    const promises = [];

    const users = usersjson;
    for( const user of users ) {
        const promise = updateUser( user ); // <-- Note this is *NOT* awaited here.
        promises.push( promise );
    }

    await Promise.all( promises ); // <-- This is where we await everything.
}

async function updateUser( user ) {
    
    try {
        const data = await getUser( url, user.Id, 'Id' );
        if( data.users.length === 0 ) {
            let createResult = await newUser( url, user );
            console.log( "Created new user %o", createResult  );
        }
        else {
            const updateResult = await updateUser( url, user, data.users[0].id );
            console.log( "Update user %o: Result: %o", user.Id, updateResult );
        }
    }
    catch( err ) {
        console.error( "Failed to update (or create) user with UserId %o: %o", user.userId, err );
    }
}



推荐阅读