我正在尝试从另一个异步函数('parent')中调用异步函数('child')。为了使事情变得复杂,父函数公开了一个双API(回调+承诺)。这是使用Q库的 defer()和 nodeify()完成的,如下所示:
var parent = function(p_arg, callback) {
var deferred = Q.defer();
child(arg, function(err, cb_arg) {
if(err)
deferred.reject(err);
else
deferred.resolve(cb_arg);
});
//If a callback was supplied, register it using nodeify(). Otherwise, return a promise.
if(callback)
deferred.promise.nodeify(callback);
else
return deferred.promise;
}
请注意,子函数不会返回promise。现在,根据传递给子回调(cb_arg)的参数的值,我可能决定对父进行一次新的调用,尽管有一个修改过的参数(p_arg)。我如何记住父母API的双重性质?
这是我迄今为止所能提出的:
child(arg, function(err, cb_arg) {
if(err)
deferred.reject(err);
else if(cb_arg.condition) {
/*Make a fresh call to parent, passing in a modified p_arg*/
if(callback)
parent(p_arg + 1, callback);
else
deferred.promise = parent(p_arg + 1);
/*
^ Is this the correct way to do this?
My goal is to return the promise returned by the fresh parent() call,
so how about I just assign it to the current parent() call's deferred.promise?
*/
}
else
deferred.resolve(cb_arg);
});
更新:好的,我对这个问题有一点清晰的认识。我现在认为实际需要做的是以下几点:
child(arg, function(err, cb_arg) {
if(err)
deferred.reject(err);
else if(cb_arg.condition) {
/*Make a fresh call to parent, passing in a modified p_arg*/
if(callback)
parent(p_arg + 1, callback);
else
parent(p_arg + 1)
.then(function(p_ret) {
deferred.resolve(p_ret);
}, function(p_err) {
deferred.reject(p_err);
});
}
else
deferred.resolve(cb_arg);
});
这种模式似乎适用于我的特定用例。但是,如果这种方法存在明显的异步相关错误,请告诉我。
答案 0 :(得分:0)
如何记住父级API的双重性质?
别。当你有可用时,只需使用promises。
顺便说一句,您可以使用Q.ncall
而不是手动使用延迟。并且您无需明确测试回调,nodeify
会在您通过undefined
时处理它。
deferred.promise = parent(p_arg + 1);
这是正确的方法吗? 我的目标是返回新的parent()调用返回的promise, 那我怎么把它分配给当前的parent()调用的deferred.promise?
您将使用.then()
并从回调中返回一个新的承诺来链接操作,为最后一个操作的结果获取新的承诺。
var promise = child().then(function(res) {
if (condition(res))
return parent(); // a promise
else
return res; // just pass through the value
});
更新:[...]此模式似乎适用于我的特定用例。
这是deferred antipattern的变体。你不想使用它。特别是,在传递回调的情况下,它似乎会留下一个悬挂(永不解决)延迟的附加回调。
你应该做的只是
function parent(p_arg, callback) {
return Q.nfcall(child, arg)
.then(function(cb_arg) {
if (cb_arg.condition) {
return parent(p_arg + 1, callback);
else
return cb_arg;
})
.nodeify(callback);
}