繁体   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