简体   繁体   English

如何处理承诺的失败Ajax请求

[英]How to handle failed ajax request with promise

I am making multiple ajax requests like this 我正在这样发出多个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() {}); 

If any of the promise( imgPromise1 or imgPromise2 ) fails then it didn't go to Promise.all . 如果任何诺言( imgPromise1imgPromise2 )失败,那么它就不会进入Promise.all

I want that in every case it should go to Promise.all . 我希望在任何情况下都应转到Promise.all

you are using then in the wrong place. 您正在使用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
});

MDN page for Promise.all Promise.all的MDN页面

Depending on the version of jQuery you are using you can use .catch and return something in catch that the promise will resolve with. 根据您使用的jQuery版本,您可以使用.catch并返回catch可以解决承诺的内容。

jQuery's version of Promise.all ($.when) will not reject if any of the deferred (is jQuery promise implementation) rejects. jQuery的Promise.all($ .when)版本将不会拒绝任何延迟的(是jQuery promise实现)拒绝。

This is only since version 3 since jQuery's deferred before this version did not behave like standardized promises (the promises native to modern browsers). 这仅是从版本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> 

However, you try the same with version 2 of jQuery and it won't work because implementation of deferred/promise is not like standard promises in versions lower than 3. You could convert Deferred to real promise but if you want to support older browsers you need Promise polyfil : 但是,您尝试使用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> 

To wait until all promises finish their tasks (resolve and/or reject) we return value of catch() for each promise. 为了等到所有promise完成其任务(解决和/或拒绝),我们为每个promise return catch()值。

In this case we use .then() to receive all information. 在这种情况下,我们使用.then()接收所有信息。

We can filter both rejected and resolved data using filterInformation helper function. 我们可以使用filterInformation辅助函数来过滤拒绝和已解决的数据。

Example: 例:

 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