node.js - 如何与 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,而不是一个一个地运行?
解决方案
首先,将处理每个单独值的代码流
user
移动到它自己的单独async
函数中。- 由于
async
函数的实际工作方式(因为每个函数都标记了每个异步状态机的边界),在语句async function
中执行并发异步工作实际上并不可行。for
- 由于
从
for
循环中调用该函数。总是更
===
喜欢==
。使用打字稿。在没有 TypeScript 的情况下使用
async
JavaScript 是一个痛苦的世界,因为您需要跟踪哪些函数返回Promise<T>
与哪些不返回,以及正确解包Promise<T>
对象。只要有可能,总是有你自己的
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 );
}
}
推荐阅读
- html - 在 H1 内使用跨度时,H1 未水平居中(仅添加到右侧)
- php - 使用 Firebase 的 Laravel 推送通知
- html - linux上的vscode,安装并启用了智能感知,但无法正常工作
- c++ - 如何实现添加和删除数组元素?
- android - 当应用在 Google Play 商店上线时,用户是否也能看到额外的成就?
- c# - C# 二叉树 2D 打包算法 旋转
- laravel-dusk - 如何使 scrollIntoView 方法在 Laravel 黄昏中工作
- shell - 用于数据排列的 shell 脚本
- python - 1个方向的误差线,但方向因点而异
- nginx-config - NGINX如何将所有流量从端口重定向到文件夹