2015-08-19 103 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. 
});