按顺序解析Javascript承诺列表?
我的实际代码非常复杂,但我将尽可能简化:按顺序解析Javascript承诺列表?,javascript,node.js,promise,es6-promise,Javascript,Node.js,Promise,Es6 Promise,我的实际代码非常复杂,但我将尽可能简化: let counter = 0 console.log("time counter: ", counter) setInterval(() => { counter = counter + 1; console.log("time counter: ", counter) }, 1000) const myPromises = [ new Promise((resolve, reject) => setTimeout(
let counter = 0
console.log("time counter: ", counter)
setInterval(() => {
counter = counter + 1;
console.log("time counter: ", counter)
}, 1000)
const myPromises =
[ new Promise((resolve, reject) => setTimeout(() => {
console.log("reject(1)")
reject(1)
}, 5 * 1000)) // after 5 seconds.
, new Promise(resolve => setTimeout(() => {
console.log("resolve(2)")
resolve(2)
}, 3 * 1000)) // after 3 seconds.
, new Promise(resolve => setTimeout(() => {
console.log("resolve(3)")
resolve(3)
}, 3 * 1000)) // after 3 seconds.
, new Promise((resolve, reject) => setTimeout(() => {
console.log("reject(4)")
reject(4)
}, 1 * 1000)) // after 1 second.
]
async function testIt(){
const results = myPromises.map(async promise => {
return new Promise((resolve) => {
// no matter what happens with the individual promise itself, we resolve.
promise
.then(ok => {
resolve({ wasSuccessful: true, result: ok })
})
.catch(err => {
resolve({ wasSuccessful: false, error: err })
})
})
})
// should be no need to catch anything here. use await.
const results_ = await Promise.all(results)
console.log("results_: ", results_)
}
testIt()
.catch(err => console.log("this error isn't supposed to happen error: ", err))
我基本上希望做到以下几点:
一,。启动第一个承诺myPromises[0]。等5秒钟。然后拒绝它
二,。开始下一个承诺我的承诺[1]。等3秒钟。解决它
在这一点上,我们有8秒的时间在计数器上
三,。开始下一个承诺我的承诺[2]。再等3秒钟。解决它
此时计数器上有8+3=11秒
四,。开始下一个承诺我的承诺[3]。。等一秒钟。。解决它
我想你会接受这个想法的。。现在怎么做
注意这不是那么。那么。那么。。我没有像我在这个话题的其他问题中看到的那样减少/积累这个列表。我不想因为任何原因被拒绝
相反,我想要一个结果列表。像这样:
results_: [
{ wasSuccessful: false, error: 1 },
{ wasSuccessful: true, result: 2 },
{ wasSuccessful: true, result: 3 },
{ wasSuccessful: false, error: 4 }
]
但请注意我的console.log输出。。即使我得到了正确的结果,它也显示了真正的执行顺序:
time counter: 0
time counter: 1
resolve(4)
time counter: 2
resolve(2)
resolve(3)
time counter: 3
time counter: 4
reject(1)
results_: [
{ wasSuccessful: false, error: 1 }, // note the array ordering is correct. rejected,
{ wasSuccessful: true, result: 2 }, // resolved,
{ wasSuccessful: true, result: 3 }, // resolved,
{ wasSuccessful: false, error: 4 } // rejected. good.
]
time counter: 5
time counter: 6
time counter: 7
基本上,这些承诺是并行发出的,无论哪个超时更快,都会更快地得到解决
相反,我希望它是这样的:
time counter: 0
time counter: 1
time counter: 2
time counter: 3
time counter: 4
time counter: 5
reject(1)
time counter: 6
time counter: 7
time counter: 8
resolve(2)
time counter: 9
time counter: 10
time counter: 11
resolve(3)
time counter: 12
resolve(4)
results_: [
{ wasSuccessful: false, error: 1 },
{ wasSuccessful: true, result: 2 },
{ wasSuccessful: true, result: 3 },
{ wasSuccessful: false, error: 4 }
]
time counter: 13
time counter: 14
...
这是简化。实际上,我所拥有的30k+记录列表——我需要对其执行一些api操作,并从本质上解决一个承诺。
我将这个列表分组在每个10个元素的子列表中。我将并行运行每个子列表
但是大名单。。又名列表列表。。需求顺序:
bigList = [ [ small parallel list 0 ], [ small parallel list 1 ] .. ]
在这个平行的承诺中,每一个承诺都已经是计算密集型的了。
我很幸运,如果我能并行运行10次。这就是为什么大列表必须是连续的。否则,它将点燃一棵有3万片叶子的承诺树,这将使某些东西崩溃
仍然不确定这种规模是否现实,但在我实现了这个序列之后,我将能够确定
那么,如何按顺序运行上述4个承诺?谢谢。所有这些承诺都是同时开始的,所以您可以并行运行它们 您可以在数组中使用promise的executor函数,然后在reduce而不是map中运行executor 设计数器=0 console.logtime计数器:,计数器 让int=setInterval=>{ 计数器=计数器+1; console.logtime计数器:,计数器 }, 1000 setTimeout=>clearIntervalint,15000; 我的承诺执行人= [解决,拒绝=>setTimeout=>{ console.log1 拒绝1 },5*1000//5秒后。 ,resolve=>setTimeout=>{ console.logresolve2 决议2 },3*1000//3秒后。 ,resolve=>setTimeout=>{ console.logresolve3 决议3 },3*1000//3秒后。 ,解析,拒绝=>setTimeout=>{ 控制台2.4 拒绝4 },1*1000//1秒钟后。 ] 异步函数测试{ const results=等待我的承诺执行人。reduceasync promise,exec=>{ const ret=等待承诺; 试一试{ const ok=等待新的承诺执行人; ret.push{wasSuccessful:true,result:ok}; }捕手{ ret.push{wasSuccessful:false,error:err}; } 返回ret; },承诺。决心 console.logresults\,results }
睾丸 所有这些承诺都是同时开始的,所以你在并行运行它们 您可以在数组中使用promise的executor函数,然后在reduce而不是map中运行executor 设计数器=0 console.logtime计数器:,计数器 让int=setInterval=>{ 计数器=计数器+1; console.logtime计数器:,计数器 }, 1000 setTimeout=>clearIntervalint,15000; 我的承诺执行人= [解决,拒绝=>setTimeout=>{ console.log1 拒绝1 },5*1000//5秒后。 ,resolve=>setTimeout=>{ console.logresolve2 决议2 },3*1000//3秒后。 ,resolve=>setTimeout=>{ console.logresolve3 决议3 },3*1000//3秒后。 ,解析,拒绝=>setTimeout=>{ 控制台2.4 拒绝4 },1*1000//1秒钟后。 ] 异步函数测试{ const results=等待我的承诺执行人。reduceasync promise,exec=>{ const ret=等待承诺; 试一试{ const ok=等待新的承诺执行人; ret.push{wasSuccessful:true,result:ok}; }捕手{ ret.push{wasSuccessful:false,error:err}; } 返回ret; },承诺。决心 console.logresults\,results }
睾丸 只是一些伪代码,用于说明您的实际问题。fn是你将要执行的动作,它应该回报你的承诺
async function run_in_chunks(fn, records, chunk_size) {
for (let chunk of chunkify(records, chunk_size))
await run_parallel(fn, chunk)
}
async function run_parallel(fn, records) {
await Promise.all(records.map(r => run_and_handle_error(fn, r)))
}
async function run_and_handle_error(fn, record) {
try {
await fn(record)
log_success(record)
} catch(e) {
log_error(record)
}
}
只是一些伪代码,用于说明您的实际问题。fn是行动 你要表演,它应该会回报你一个承诺
async function run_in_chunks(fn, records, chunk_size) {
for (let chunk of chunkify(records, chunk_size))
await run_parallel(fn, chunk)
}
async function run_parallel(fn, records) {
await Promise.all(records.map(r => run_and_handle_error(fn, r)))
}
async function run_and_handle_error(fn, record) {
try {
await fn(record)
log_success(record)
} catch(e) {
log_error(record)
}
}
现有答案提供了您可以使用的手工解决方案。但对于您的情况,我认为这种方法可以满足您的所有需求: 你给它30k条记录的列表和限制,即10条,这意味着它总是保持10个任务执行,一旦一个任务完成,它就会启动另一个任务
如果您需要使用承诺,那么请记住,一旦您创建了承诺,它就开始在后台执行,您无法控制它,所以您需要使用某种工厂方法。这意味着当执行方法时,就会产生承诺。现有答案提供了您可以使用的手工解决方案。但对于您的情况,我认为这种方法可以满足您的所有需求: 你给它30k条记录的列表和限制,即10条,这意味着它总是保持10个任务执行,一旦一个任务完成,它就会启动另一个任务
如果您需要使用承诺,那么请记住,一旦您创建了承诺,它就开始在后台执行,您无法控制它,所以您需要使用某种工厂方法。这意味着方法在执行时会产生承诺。。。事实上,我在这里调用了新的承诺执行函数。。这已经开始行动了?我在想只有当你打电话或使用wait时才会开始。你说我的承诺是同时开始的-你是说在我的阵列中?他们已经开始执行了。。这一点很重要的原因是,我可能无法以你们在这里展示的方式让这个遗嘱执行人。这只是一个过于简化的示例,实际代码非常复杂,可能无法工作。我会随时通知你的。现在谢谢你:很有意思。。事实上,我在这里调用了新的承诺执行函数。。这已经开始行动了?我在想只有当你打电话或使用wait时才会开始。你说我的承诺是同时开始的-你是说在我的阵列中?他们已经开始执行了。。这一点很重要的原因是,我可能无法以你们在这里展示的方式让这个遗嘱执行人。这只是一个过于简化的示例,实际代码非常复杂,可能无法工作。我会随时通知你的。现在谢谢你: