簡體   English   中英

如何處理承諾的失敗Ajax請求

[英]How to handle failed ajax request with promise

我正在這樣發出多個ajax請求

 imgPromises = []; imgPromise1 = $.ajax({ url: s3Url, type: "POST", data: s3FormData, mimeType: "multipart/form-data", contentType: false, cache: false, processData: false }).done(function(data, status, formXHR) { x = formXHR['responseText'].toString(); var uploadedUrl = x.match("<Location>(.*)</Location>")[1]; if ($(this).attr('id').startsWith('inp')) { if ($(this).attr('id').startsWith('inp')) $('footer').css('background-image', 'url(' + uploadedUrl + ')'); footerBackground = $('footer').css('background'); } }).fail(function() { console.log("in ajax fail"); }.bind(this)); imgPromises.push(imgPromise1); imgPromise2 = $.ajax({ url: s3Url, type: "POST", data: s3FormData, mimeType: "multipart/form-data", contentType: false, cache: false, processData: false }).done(function(data, status, formXHR) { x = formXHR['responseText'].toString(); var uploadedUrl = x.match("<Location>(.*)</Location>")[1]; if ($(this).attr('id').startsWith('inp')) { if ($(this).attr('id').startsWith('inp')) $('footer').css('background-image', 'url(' + uploadedUrl + ')'); footerBackground = $('footer').css('background'); } }).fail(function() { console.log("in ajax fail"); }.bind(this)); imgPromises.push(imgPromise2); Promise.all(imgPromises.then(function() {}); 

如果任何諾言( imgPromise1imgPromise2 )失敗,那么它就不會進入Promise.all

我希望在任何情況下都應轉到Promise.all

您正在使用then在錯誤的地方。

const Fail = function(error){this.error=error;};//special Fail type value
const isFail = o=>(o&&o.constructor)===Fail;//see if item passed is fail type
const isNotFail = o => !isFail(o);//see if item passed is not fail type
Promise.all(imgPromises
  .map(
    p=>Promise.resolve(p)/**convert to real promise*/
  ).map(
    p=>p.catch(error=>new Fail(error))//single request failed, resolve with Fail value
  )
)
.then(function (responses) {
  // successes = responses.filter(isNotFail)
  // failed = responses.filter(isFail)
})
.catch(function (err) {
  //handle error
});

Promise.all的MDN頁面

根據您使用的jQuery版本,您可以使用.catch並返回catch可以解決承諾的內容。

jQuery的Promise.all($ .when)版本將不會拒絕任何延遲的(是jQuery promise實現)拒絕。

這僅是從版本3開始,因為jQuery在此版本之前推遲的行為不像標准化的承諾(現代瀏覽器中的原始承諾)那樣。

 function makeRequest(num){//returning $.Deferred like $.ajax will var d = $.Deferred(); setTimeout(() => { if(num>1){//reject if number passed is higher than 1 d.reject("Rejecting over one"); return; } d.resolve(num) }, 10); return d.promise(); } $.when.apply(//jQueries Promise.all need apply to pass array of "promises" $, [1,2].map(//map numbers 1 and 2 to deferred 1 will resolve 2 rejects function(num){ return makeRequest(num) .catch(//catch rejected deferred function(error){return "error in:"+num; }//resolve with this ); } ) ).then(//both deferred (=jQuery promise like) are resolved function(){ console.log("it is done",[].slice.apply(arguments)); } ) 
 <script src="https://code.jquery.com/jquery-3.3.1.min.js" integrity="sha256-FgpCb/KJQlLNfOu91ta32o/NMZxltwRo8QtmkMRdAu8=" crossorigin="anonymous"></script> 

但是,您嘗試使用jQuery版本2進行相同操作,但由於延期/承諾的實現與低於3的版本中的標准承諾不同,因此無法正常工作。您可以將Deferred轉換為真實承諾,但是如果您想支持較舊的瀏覽器,則可以需要Promise polyfil

 console.log("jQuery version",jQuery.fn.jquery); function makeRequest(num){//function returning jQuery deferred (could be $.ajax) var d = $.Deferred(); if(num>1){ //now this will throw an error throw("Rejecting over one"); } setTimeout(() => { d.resolve(num) }, 10); return d.promise(); } Promise.all( [1,2].map( function(num){ //convert deferred to real Promise (having catch) if makeRequest throws then promise is rejected return Promise.resolve().then(()=>makeRequest(num)) .catch( function(error){return "error in:"+num; }//resolve to error in... string ); } ) ).then( function(){ console.log("it is done",[].slice.apply(arguments)); } ) 
 <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script> 

為了等到所有promise完成其任務(解決和/或拒絕),我們為每個promise return catch()值。

在這種情況下,我們使用.then()接收所有信息。

我們可以使用filterInformation輔助函數來過濾拒絕和已解決的數據。

例:

 const mockResolvePromise = (message) => { return new Promise((resolve) => { resolve(message) }) } const mockRejectPromise = (messageError) => { return new Promise((_, reject) => { reject(messageError) }) } const ajax0 = mockResolvePromise({ nice: 'data' }) const ajax1 = mockRejectPromise('bad error'); const ajax2 = mockRejectPromise('semi bad error'); const ajax3 = mockRejectPromise('super bad error'); const ajax4 = mockResolvePromise({ hello: 'handsome' }) const promises = [ajax0, ajax1, ajax2, ajax3, ajax4]; // Now lets add catch const promisesWithCatch = promises.map(p => p.catch(e => { return { error: e } })) const filterInformation = (stuff) => { return stuff.reduce((prev, current) => { if (current.error) return { ...prev, errors: [...prev.errors, current.error] }; return { ...prev, data: [...prev.data, current] } }, { errors: [], data: [] }) } Promise.all(promisesWithCatch) .then(filterInformation) .then(data => console.log(data)) 
 <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script> 

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM