JavaScript 中的异步函数递归和 Bluebird Promises
Recursion with Asynchronous Functions and Bluebird Promises in JavaScript
在JavaScript中,我有四组函数:
Set_A
synchronousFunction_One
synchronousFunction_Two
synchronousFunction_Three
synchronousFunction_Four
synchronousFunction_Five
Set_B
objectA.asynchronousFunction_One
objectA.asynchronousFunction_Two
.
.
.
objectA.asynchronousFunction_N
Set_C
objectA.asynchronousFunction_Three
objectA.asynchronousFunction_Four
.
.
.
objectA.asynchronousFunction_M
Set_D
synchronousFunction_Six
我需要每个集合 运行 一个接一个,按照特定的顺序并有一定的限制:
- None Set_A 中的函数可以被调用,直到外部提供的承诺解决
- 迭代Set_A中的同步函数,每个调用一次
- 每次调用 Set_A 中的函数后,迭代器暂停并等待下面的第 4 步和第 5 步解决,然后再移至 Set_A[=34= 中的下一个元素]
- Set_B 被迭代,每个方法被调用一次,打开几个异步连接到互联网
- 一旦步骤 4 中的所有调用都已解决,Set_C 将迭代并调用每个方法一次,再次打开多个异步连接到互联网
- 一旦第 5 步中的所有调用都已解决,上述第 1 步中的迭代器将移至 Set_A
中的下一个元素
所以,基本上我们在这里做的是等待一些外部承诺来解决,然后我们调用函数 "prime the pump",可以这么说。然后,我们迭代对象接口的一部分,即 "independent part"-- 可以随时调用的方法。然后,我们迭代该对象接口的另一部分,"the dependent part"(即依赖部分中的 none 方法将正确关闭,除非独立部分中的所有方法至少关闭一次)。最后,我们调用清理函数。完成后,我们从 Set_A 中的下一个元素重新开始并再次启动泵。
最高级别的抽象,再次使用 Bluebird Promise 库,如下所示:
function doAllTheThings( externalPromise ) {
var Set_A, Set_B, Set_C; // Array<Function>
return new Promise( promiseToDoAllTheThings );
function promiseToDoAllTheThings( resolve, reject ) {
externalPromise.then( go );
function go() {
var primePump = Set_A.pop();
if ( !primePump ) return;
primePump();
callEverythingInSet_B()
.then( callEverythingInSet_C )
.then( cleanUp )
;
}
function callEverythingInSet_B() {
var promises = [];
for ( var index in Set_B )
promises.push( Set_B[index]() );
return Promise.all( promises );
}
function callEverythingInSet_C() {
var promises = [];
for ( var index in Set_C )
promises.push( Set_C[index]() );
return Promise.all( promises );
}
function cleanUp() {
// Do stuff
go();
}
}
}
我真的很难过;昨天我花了几个小时进行分解和重构,每次都没有得到我预期的行为。我仍在编写我的实际代码;所以也许我会找到让我发疯的奇怪分号或类似的东西。
但与此同时,我想我应该 post 在这里问问——我对 Bluebird Promise Library 的理解是否正确?鉴于上面的代码,人们是否应该期待我所描述的行为?如果没有——你能提供一些演示代码吗?
我的毛囊谢谢你。
是的,这似乎有效。但是,一些提示:
- 不要将
go()
函数的调用放在 cleanUp
中。将它链接在 go
函数本身的 .then(cleanUp)
之后,使递归性质显而易见(并保持本地引用)。
那个
return new Promise( promiseToDoAllTheThings );
function promiseToDoAllTheThings( resolve, reject ) {
错了。返回的承诺永远不会被解决或拒绝,您不使用这些回调。不过,你连shouldn't use them here都没有。省略那个promiseToDoAllTheThings
,只做一个
return externalPromise.then( go );
直接。
- 而不是那些普通的
for
循环,尝试使用 Array::map
,它看起来会更好:-)
- 您可以使用
Promise.each
而不是 go
循环
在JavaScript中,我有四组函数:
Set_A
synchronousFunction_One
synchronousFunction_Two
synchronousFunction_Three
synchronousFunction_Four
synchronousFunction_Five
Set_B
objectA.asynchronousFunction_One
objectA.asynchronousFunction_Two
.
.
.
objectA.asynchronousFunction_N
Set_C
objectA.asynchronousFunction_Three
objectA.asynchronousFunction_Four
.
.
.
objectA.asynchronousFunction_M
Set_D
synchronousFunction_Six
我需要每个集合 运行 一个接一个,按照特定的顺序并有一定的限制:
- None Set_A 中的函数可以被调用,直到外部提供的承诺解决
- 迭代Set_A中的同步函数,每个调用一次
- 每次调用 Set_A 中的函数后,迭代器暂停并等待下面的第 4 步和第 5 步解决,然后再移至 Set_A[=34= 中的下一个元素]
- Set_B 被迭代,每个方法被调用一次,打开几个异步连接到互联网
- 一旦步骤 4 中的所有调用都已解决,Set_C 将迭代并调用每个方法一次,再次打开多个异步连接到互联网
- 一旦第 5 步中的所有调用都已解决,上述第 1 步中的迭代器将移至 Set_A 中的下一个元素
所以,基本上我们在这里做的是等待一些外部承诺来解决,然后我们调用函数 "prime the pump",可以这么说。然后,我们迭代对象接口的一部分,即 "independent part"-- 可以随时调用的方法。然后,我们迭代该对象接口的另一部分,"the dependent part"(即依赖部分中的 none 方法将正确关闭,除非独立部分中的所有方法至少关闭一次)。最后,我们调用清理函数。完成后,我们从 Set_A 中的下一个元素重新开始并再次启动泵。
最高级别的抽象,再次使用 Bluebird Promise 库,如下所示:
function doAllTheThings( externalPromise ) {
var Set_A, Set_B, Set_C; // Array<Function>
return new Promise( promiseToDoAllTheThings );
function promiseToDoAllTheThings( resolve, reject ) {
externalPromise.then( go );
function go() {
var primePump = Set_A.pop();
if ( !primePump ) return;
primePump();
callEverythingInSet_B()
.then( callEverythingInSet_C )
.then( cleanUp )
;
}
function callEverythingInSet_B() {
var promises = [];
for ( var index in Set_B )
promises.push( Set_B[index]() );
return Promise.all( promises );
}
function callEverythingInSet_C() {
var promises = [];
for ( var index in Set_C )
promises.push( Set_C[index]() );
return Promise.all( promises );
}
function cleanUp() {
// Do stuff
go();
}
}
}
我真的很难过;昨天我花了几个小时进行分解和重构,每次都没有得到我预期的行为。我仍在编写我的实际代码;所以也许我会找到让我发疯的奇怪分号或类似的东西。
但与此同时,我想我应该 post 在这里问问——我对 Bluebird Promise Library 的理解是否正确?鉴于上面的代码,人们是否应该期待我所描述的行为?如果没有——你能提供一些演示代码吗?
我的毛囊谢谢你。
是的,这似乎有效。但是,一些提示:
- 不要将
go()
函数的调用放在cleanUp
中。将它链接在go
函数本身的.then(cleanUp)
之后,使递归性质显而易见(并保持本地引用)。 那个
return new Promise( promiseToDoAllTheThings ); function promiseToDoAllTheThings( resolve, reject ) {
错了。返回的承诺永远不会被解决或拒绝,您不使用这些回调。不过,你连shouldn't use them here都没有。省略那个
promiseToDoAllTheThings
,只做一个return externalPromise.then( go );
直接。
- 而不是那些普通的
for
循环,尝试使用Array::map
,它看起来会更好:-) - 您可以使用
Promise.each
而不是go
循环