我已经使用了dojo,但并不完全关注dojo.Deferred
(或者至少我没有使用所有可用的功能)。我一直在做一些关于它的阅读,并想知道以下场景是否适合将Deferred用作更优雅的方法?或者如果不延迟,是Promise
还是在dojo中可用的其他类型的链接技术可以以更易读/顺序的方式实现以下目的?
var _this = this;
var secondCallback = function( res ) {
console.debug('All is complete Result [' + res +']');
};
var firstCallback = function( res ) {
if(res == 'true')
my.lib.processRPC( my.rpc.module.DoSecondStep( _this.user_id ), secondCallback );
};
my.lib.processRPC( my.rpc.module.CheckFirstStep(), firstCallback );
如果是这样,这看起来怎么样? Deferred如何在这里使用?任何帮助将不胜感激。
答案 0 :(得分:1)
我用一个简单的window.setTimeout来愚弄您的RPC模块,以便在网络延迟后模拟异步回调,并用_this_user_id替换_this.user_id,以及可能的其他调整。
可运行的示例:http://dojo-sandbox.net/public/4c296/0
/* In resopnse to http://stackoverflow.com/questions/11217904/how-to-elegantly-structure-a-chain-of-requests-callbacks-using-dojo */
require([
"dojo/_base/Deferred"
], function(Deferred) {
var my_lib = function() {};
my_lib.processRPC = function(value, def) {
// simulate a long lived network call or whatever
window.setTimeout(function() {
console.log("rpc has fired");
def.resolve(value);
}, 1000);
}
var my_rpc_module = function() {};
my_rpc_module.CheckFirstStep = function() {
console.log("CheckFirstStep here.");
return 'true';
}
my_rpc_module.DoSecondStep = function(userid) {
console.log("CheckSecondStep here for userid " +userid + ".");
return 'finished';
}
var _this_user_id = "Mr Blobby";
var secondCallback = new Deferred();
secondCallback.then(function(res) {
console.debug('All is complete Result [' + res +']');
});
var firstCallback = new Deferred();
firstCallback.then(function( res ) {
if(res == 'true') {
my_lib.processRPC( my_rpc_module.DoSecondStep( _this_user_id ), secondCallback );
}
});
my_lib.processRPC( my_rpc_module.CheckFirstStep(), firstCallback );
})
答案 1 :(得分:0)
my.lib.processRPC
需要返回Promise进行处理。 "Deferred"是拒绝/履行承诺的接口,您可能不想导出这些方法 - 您只需从私有范围的Deferred返回Promise,可以在其上安装回调。
我不是Dojo专家,您可能需要根据确切的语法调整以下代码。一个接近你的场景的实现 - 我希望my.rpc.module.DoSecondStep( _this.user_id )
只是一个创建选项对象的函数 - 看起来像这样:
my.lib.processRPC = function(options)
var d = new Deferred();
// ...
return d.getPromise();
// do some heavy and/or asynchronous processing and call
d.resolve(result) // somewhen in the future
};
// narrative code:
my.lib.processRPC( my.rpc.module.getFirstStep() ).then(function(result) {
if (result)
return my.lib.processRPC( my.rpc.module.getSecondStep( _this.user_id ) )
.then( function( res ) {
console.debug('All is complete Result [' + res +']');
});
else
return /* false */ result;
}).addCallback(console.log.bind(console, "everything finished"));
但我建议doStepX
函数真的应该自己处理。所以他们应该返回Deferreds / Promises(最终通过内部调用processRPC
),并在它们不成功时拒绝它们。延期将“冒泡”这样的错误。
my.rpc.module.doFirstStep = function() {
var d = new Deferred();
// ...
return d.getPromise();
// do some heavy and/or asynchronous processing and call
d.resolve(result) // or
d.reject(error) // somewhen in the future
};
my.rpc.module.doSecondStep = function(id) {
// returning a Promise, as above
};
// really narrative code:
my.rpc.module.doFirstStep()
.then(my.rpc.module.doSecondStep)
.addCallbacks(function( res ) {
console.log('All is complete Result [' + res +']');
}, function (err) {
console.log('Something happened: [' + err +']');
});
请注意doSecondStep
接收第一个延迟的(成功)结果作为参数。如果您不想要或不需要在不调用的情况下指定其他参数,则需要使用类似.bind()
或包装函数的内容:
...then(function firstCallback() {
return my.rpc.module.DoSecondStep( _this.user_id );
})...