按顺序解析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时才会开始。你说我的承诺是同时开始的-你是说在我的阵列中?他们已经开始执行了。。这一点很重要的原因是,我可能无法以你们在这里展示的方式让这个遗嘱执行人。这只是一个过于简化的示例,实际代码非常复杂,可能无法工作。我会随时通知你的。现在谢谢你: