在下面的程序中,当最初调用recurse(prog)
时(第64行),它递归地挖掘exp
(第1行)中描述的表达式prog
,在这种情况下切换exp.type = A,B或C.
在递归调用的最底层(当大小写(" C"))时,我调用verySlowMan(exp.value)
查找collections
列表以检查是否名称为exp.value的集合是否存在。
如果是,则返回集合
如果不是,则返回新的Error
问题是verySlowMan()
花时间检索一个集合。
为简单起见,我提出了一个简单的if else
条件,但verySlowMan
最终会发出XHR请求。所以这是不可预测的慢
问题如下:
如何在递归调用中传播verySlowMan的返回值,以便在调用recurse(prog)时得到一个很好的集合列表?
目前,出于可以理解的原因,我得到[null,[null,null],null]。但我真的不知道如何解决它。
我试图从verySlowMan
返回deferred.promises,但在这种情况下,我认为recurse()也应该为每个递归调用返回一个新的promise。
(1)我不确定如何正确地做到这一点
(2)我怀疑它是最好的方式
注意:prog
,collections
中的项目数量和递归()中的案例可能会变得很长。
以下是该计划:
var prog = {
type : "A", value : [
{ type : "B", value : "C1" },
{ type : "B", value : [
{ type : "C", value : "C2" },
{ type : "C", value : "end" }
]},
{ type : "B", value : "C3" }
]
}
var collections = [
{ name : "C1", data : ["item1", "item2", "item3"]},
{ name : "C2", data : ["item1", "item2", "item3"]}
]
function verySlowMan( collectionToFind ){
collections.forEach(function(collection){
if ( collection.name === collectionToFind ) {
return collection;
}else{
return new Error("No Collection");
}
});
return null;
}
function recurse(exp){
switch(exp.type){
case("A"):
var As = [];
exp.value.forEach( function(B){
As.push ( recurse(B) );
} );
return As;
break;
case("B"):
var Bs = [];
if (typeof(exp.value) === 'string') {
return verySlowMan( exp.value );
} else {
exp.value.forEach( function(C){
Bs.push ( recurse(C) );
} );
return Bs;
}
break;
case("C"):
return verySlowMan( exp.value );
break;
default:
throw new Error('wrong type');
}
}
console.log( recurse(prog) ); // -> [ null, [ null, null ], null ]
答案 0 :(得分:1)
以下是promises的例子。
function verySlowMan( collectionToFind ) {
return new Promise(function(resolve, reject) {
setTimeout(function() {
for(var i = 0; i < collections.length; i++) {
if ( collections[i].name === collectionToFind ) {
resolve(collections[i]);
return;
}
}
reject(new Error("No Collection"));
}, 100);
});
}
function recurse(exp){
function errorHandler(err) {
if(err.message === "No Collection") return null;
else throw err;
};
switch(exp.type){
case("A"):
return Promise.all(exp.value.map(recurse));
case("B"):
if (typeof(exp.value) === 'string') {
return verySlowMan(exp.value).catch(errorHandler);
} else {
return Promise.all(exp.value.map(recurse));
}
case("C"):
return verySlowMan( exp.value ).catch(errorHandler);
default:
return Promise.reject(new Error('wrong type'));
}
}
recurse(prog).then(function(result) {
console.log(result);
}).catch(function(err) {
console.log(err.stack);
});