0

我已经使用过很多dojo,但并没有完全理解dojo.Deferred(或者至少我没有使用所有可用的功能)。我一直在阅读它,并想知道以下场景是否适合使用 Deferred 作为更优雅的方法?或者,如果不是 Deferred,Promisedojo 中是否有其他类型的链接技术可以以更具可读性/顺序性的方式实现以下目标?

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 在这里如何使用?任何帮助将不胜感激。

4

2 回答 2

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 );

})
于 2012-06-27T10:22:18.907 回答
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内部调用),并在不成功时拒绝它们。Deferred 将“冒泡”此类错误。

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接收第一个 deferred 作为参数的(成功)结果。如果您不希望这样或需要在不调用的情况下指定其他参数,则需要使用类似.bind()或包装函数的东西:

...then(function firstCallback() {
    return my.rpc.module.DoSecondStep( _this.user_id );
})...
于 2012-06-27T18:45:13.817 回答