Как обработать неудачный запрос ajax с обещанием - PullRequest
0 голосов
/ 11 июня 2018

Я делаю несколько запросов 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() {});

Если какое-либо из обещаний (imgPromise1 или imgPromise2) не выполнено, оно не перейдет к Promise.all.

Я хочу, чтобыв каждом случае это должно идти к Promise.all.

Ответы [ 3 ]

0 голосов
/ 11 июня 2018

В зависимости от версии jQuery, которую вы используете, вы можете использовать .catch и возвращать что-то в улове, с которым обещание разрешится.

Версия Promise.all в jQuery ($ .when) не будет отклонена, если отклонено какое-либо из отложенных (реализация обещаний jQuery).

Это только начиная с версии 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>

Однако вы пытаетесь сделать то же самое с версией 2 jQuery, и она не будет работать, потому что реализация deferred / обещания не похожа на стандартные обещания в версиях ниже, чем3. Вы можете конвертировать Отложенное в реальное обещание, но если вы хотите поддерживать старые браузеры, вам нужен Полифил Promise :

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>
0 голосов
/ 11 июня 2018

Чтобы дождаться, пока все обещания завершат выполнение своих задач (разрешить и / или отклонить), мы 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>
0 голосов
/ 11 июня 2018

вы используете 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 страница для Promise.all

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...