承诺在定义而不是 Promises.all 时执行?
Promises execute when defined instead of Promises.all?
我正在尝试创建一个 promise 数组,这样我就可以批量处理 promises 而不是一起执行它们以避免关闭我的服务器。我想一次执行最多 20 个承诺。
我写了下面的代码:
let promises = [];
let create;
let update;
let i=0;
let users = users.json;
if (users && usersjson.users.length) {
for (const user of users) {
if (userexists) {
update = new promise(async (resolve,reject) => {
//Function to update user
});
promises.push(update);
i++;
} else {
create = new promise (async (resolve,reject) => {
//Function to create a new user
});
promises.push(update);
i++;
}
if (promises.length >= 20 || i >= usersjson.users.length) {
await Promise.all(promises)
.then((response)=>{
console.log(response);
promises=[];
}).catch((err)=> {
console.log(err);
})
}
}
}
但是我发现promise是在我定义的时候执行的,而不是在我调用Promise.all的时候被压入数组中执行的,我想不通为什么。
我还希望 Promise.all 函数继续 运行 即使单个承诺被拒绝,如果我的代码构建方式可能的话。如果代码失败,我在每个承诺中都有一个陷阱,这是正确的方法吗?
Javascript中的函数直接执行。与 Promise 的不同之处在于您可以以 Promise 风格的方式等待它。当函数被调用时,就像您在 for 循环中所做的那样,它会立即执行。稍后,使用 Promise.all
,您只是在说:“等待我在数组中定义的承诺完成”(如果其中一个失败则出错)。
关于你的第二个问题,有一种方法可以等待所有承诺完成,而不是抛出错误(并因此停止)。那是 Promise.allSettled。顾名思义,就是等待所有的 promises 结算。
但是,请记住响应将不同于 Promise.all
函数。 As stated in the docs,如果函数是 'fulfilled' 或 'rejected',它会 return 每个承诺的数组。
如评论中所述,promise 对象实际上在您执行异步操作后立即进入“待定”状态,并在操作完成后立即“完成”。
所以在您的代码中,您实际上为所有用户创建和 运行 异步操作,而不仅仅是其中的 20 个用户。
有两种解决方案适合您。主要的是创建 return 一个承诺并且 运行 一次只有 20 个的函数。
const jobs = users.map(user => () => user.update(...)); // array of functions
while (jobs.length > 0) {
await Promise.all(jobs.splice(0,20).map(job => job())); // take 20 and process
}
另一种解决方案是使用像 bluebird which has a lot of useful methods for working with promises. One you'd probably like is map()
which support concurrency limit.
这样的库
你的第二个问题是关于 Promise.all
中的错误导致整个系列失败的原因。
为了防止您可以向每个作业添加 .catch()
,例如,在那里添加 return 和 null
或任何其他值,这将帮助您确定某些操作失败。当然,这种做法也会防止Promise.all
被打断。
const jobs = users.map(user => () => user.update().catch(e => null));
我正在尝试创建一个 promise 数组,这样我就可以批量处理 promises 而不是一起执行它们以避免关闭我的服务器。我想一次执行最多 20 个承诺。 我写了下面的代码:
let promises = [];
let create;
let update;
let i=0;
let users = users.json;
if (users && usersjson.users.length) {
for (const user of users) {
if (userexists) {
update = new promise(async (resolve,reject) => {
//Function to update user
});
promises.push(update);
i++;
} else {
create = new promise (async (resolve,reject) => {
//Function to create a new user
});
promises.push(update);
i++;
}
if (promises.length >= 20 || i >= usersjson.users.length) {
await Promise.all(promises)
.then((response)=>{
console.log(response);
promises=[];
}).catch((err)=> {
console.log(err);
})
}
}
}
但是我发现promise是在我定义的时候执行的,而不是在我调用Promise.all的时候被压入数组中执行的,我想不通为什么。
我还希望 Promise.all 函数继续 运行 即使单个承诺被拒绝,如果我的代码构建方式可能的话。如果代码失败,我在每个承诺中都有一个陷阱,这是正确的方法吗?
Javascript中的函数直接执行。与 Promise 的不同之处在于您可以以 Promise 风格的方式等待它。当函数被调用时,就像您在 for 循环中所做的那样,它会立即执行。稍后,使用 Promise.all
,您只是在说:“等待我在数组中定义的承诺完成”(如果其中一个失败则出错)。
关于你的第二个问题,有一种方法可以等待所有承诺完成,而不是抛出错误(并因此停止)。那是 Promise.allSettled。顾名思义,就是等待所有的 promises 结算。
但是,请记住响应将不同于 Promise.all
函数。 As stated in the docs,如果函数是 'fulfilled' 或 'rejected',它会 return 每个承诺的数组。
如评论中所述,promise 对象实际上在您执行异步操作后立即进入“待定”状态,并在操作完成后立即“完成”。
所以在您的代码中,您实际上为所有用户创建和 运行 异步操作,而不仅仅是其中的 20 个用户。
有两种解决方案适合您。主要的是创建 return 一个承诺并且 运行 一次只有 20 个的函数。
const jobs = users.map(user => () => user.update(...)); // array of functions
while (jobs.length > 0) {
await Promise.all(jobs.splice(0,20).map(job => job())); // take 20 and process
}
另一种解决方案是使用像 bluebird which has a lot of useful methods for working with promises. One you'd probably like is map()
which support concurrency limit.
你的第二个问题是关于 Promise.all
中的错误导致整个系列失败的原因。
为了防止您可以向每个作业添加 .catch()
,例如,在那里添加 return 和 null
或任何其他值,这将帮助您确定某些操作失败。当然,这种做法也会防止Promise.all
被打断。
const jobs = users.map(user => () => user.update().catch(e => null));