2015-08-19 71 views
0

我刚开始用承诺包头,我可以使用一些指导来了解如何使此场景生效。下面的代码来自一个更大的插件文件,但我已经包含了我认为相关的部分。

有一个回调函数(callbackBeforeSend),我将执行一些异步地理位置的东西(我得到了这个工作),我需要保持ajax调用,直到这些函数完成。

我在代码中看到他们使用$ .Deferred()来处理ajax响应,我想知道是否有办法将回调函数和初始ajax调用绑定到$ .Deferred()中处理所有事情的正确执行顺序。

所以我想发生什么

  1. 回调函数的火灾
  2. 异步的事情发生在回调并返回纬度,经度,地址
  3. 阿贾克斯火的纬度,经度,地址被返回从回调

任何帮助将不胜感激。我仍然不太了解诺言,但我正在努力学习。谢谢!

$.extend(Plugin.prototype, { 
    _getData: function (lat, lng, address) { 
     var _this = this; 
     var d = $.Deferred(); 

     if (this.settings.callbackBeforeSend) { 
      this.settings.callbackBeforeSend.call(this, lat, lng, address); 
     } 

     $.ajax({ 
      type   : 'GET', 
      url   : this.settings.dataLocation + (this.settings.dataType === 'jsonp' ? (this.settings.dataLocation.match(/\?/) ? '&' : '?') + 'callback=?' : ''), 
      // Passing the lat, lng, and address with the AJAX request so they can optionally be used by back-end languages 
      data: { 
       'origLat' : lat, 
       'origLng' : lng, 
       'origAddress': address 
      }, 
      dataType  : dataTypeRead, 
      jsonpCallback: (this.settings.dataType === 'jsonp' ? this.settings.callbackJsonp : null) 
     }).done(function (p) { 
      d.resolve(p); 

      // Loading remove 
      if(_this.settings.loading === true){ 
       $('.' + _this.settings.formContainer + ' .' + _this.settings.loadingContainer).remove(); 
      } 
     }).fail(d.reject); 
     return d.promise(); 
    } 
}); 
+0

不改变这个代码,你不能这样做。我不清楚你是否编写了这个代码,或者它是否是一个无法更改的第三方库。 –

+0

我没有写这段代码,它是从插件文件中提取的。不过,我可以更改代码。我相信我需要将回调调用和ajax调用绑定到$ .Deferred函数中。 – yoxalld

+0

大部分你看起来没问题,你只需要你的'callbackBeforeSend'来返回一个promise,并在'callbackBeforeSend.then(...)'' – dave

回答

0

我真的真的不喜欢jQuery的承诺,但如果你一定要...

function callBackBeforeSend(){ 
    var def = $.Deferred(); 
    //Async operation here: 
    async(function(lat, lng, address) { 
     //pass resolve an object with all information 
     //the async callback function might not use 3 parameters, but an 
     //object containing all 
     def.resolve({ lat : lat, lng : lng, address : address}); 
     //async function callback 
    }); 
    return def.promise(); 
} 

然后你可以使用deferred.then()得到解决数据。

var prom = callbackBeforeSend(); 
prom.then(function(obj){ 
    //lat, lng, address within obj 
    //use on ajax call below. 
    $.ajax(); 
}); 

然后可以使用then到链中的方法 我还检查了正在使用的jQuery的版本。 jQuery 1.8之前的行为可能会有所不同。

下面是使用ES6承诺:

function callbackBeforeSend(){ 
    return new Promise(function(resolve) { 
     async(function(lat, lng, address){ 
      resolve({lat : lat, lng : lng, address : address}); 
     }); 
    }); 
} 

然后是同样的事情:

var prom = callbackBeforeSend(); //firstRequest 
prom.then(function(obj){ 
    //Callback finished 
    //obj holds lat, lng, address 
    //Do ajax request: 
    $.ajax(); 
}); 
0
  1. 回调函数的火灾
  2. 异步的事情发生在回调并返回 纬度,经度,地址
  3. 个阿贾克斯火的纬度,经度,地址是 从回调返回
$.when(callback()) 
.then(function(data) { 
    // `data`: `lat` , `lng`, `address` ... 
    var settings = {url:url, data:{...}, type:"GET"}; 
    return $.ajax(settings) 
}, function(jqxhr, textStatus, errorThrown) { 
    console.log(errorThrown); 
    return errorThrown 
}) 
.then(function(data) { 
    // do stuff when `callback` , `$.ajax()` completes 
}, function(err) { 
    console.log(err); 
}); 
0

可能是最重要的事情来实现的:

  • ,为需求(可选)调用在执行ajax之前的异步callbackBeforeSend(),要求Promise或者由callbackBeforeSend()返回或创建。
  • $.ajax()返回jqXHR对象,这实际上是一个Promise,因此$.ajax()不需要您创建/解析您自己的Deferred。

试试这个:

$.extend(Plugin.prototype, { 
    _getData: function (lat, lng, address) { 
     var settings = this.settings; 
     var promise = settings.callbackBeforeSend ? $.when(settings.callbackBeforeSend.call(this, lat, lng, address)) : $.when(); 
     return promise.then(function() { 
      return $.ajax({ 
       type: 'GET', 
       url: settings.dataLocation + (settings.dataType === 'jsonp' ? (settings.dataLocation.match(/\?/) ? '&' : '?') + 'callback=?' : ''), 
       data: { 'origLat':lat, 'origLng':lng, 'origAddress':address }, 
       dataType: dataTypeRead, 
       jsonpCallback: (settings.dataType === 'jsonp' ? settings.callbackJsonp : null) 
      }); 
     }).then(null, function(jqXHR, textStatus, errorThrown) { 
      return errorThrown; 
     }); 
    } 
}); 

如果settings.callbackBeforeSend()已经返回一个承诺,请$.when(...)包装可以省略。

您的“加载”指示应该(通过约定)附加在后面的代码块中 - 在_getData()之内或在调用函数中。

例如,调用函数可以调用._getData()和取得的成果进行以下操作:

var $spinner = $("#myLoadingElement").appendTo('.wherever');//pseudocode 
foo._getData(lat, lng, address).then(function(data) { 
    //do whatever on success 
}, function(error) { 
    //do whatever on error 
}).always(function() { 
    $spinner.remove();//remove the spinner regardless of the outcome. 
});