Использование jQuery deferred и promise внутри цикла

Это то, чего я пытаюсь достичь,

У меня есть отсортированный массив, который я передаю в jQuery каждый. Внутри каждого есть вызов ajax, который доставит мне нужные данные и каждый раз вставит в другой массив (давайте назовем его allJsonData). Наконец я показываю allJsonData. Проблема в том, что всякий раз, когда я отображаю allJsonData, элементы всегда отображаются непоследовательно (не в алфавитном/случайном порядке). Я ожидаю, что allJsonData будет отображаться в алфавитном порядке (сначала данные AList, затем данные BList, третьи данные CList и т. д.). Я новичок в jQuery deferred и promise. Заранее спасибо.

var sortedArray = [AList, BList, CList, DList];
var promises = [];
var allJsonData = [];
$.each(sortedArray, function (index, value) {
var dfd = $.Deferred();
var url = _spPageContextInfo.webAbsoluteUrl  + ('/_api/Web/Lists/GetByTitle(' + "'" + value + "'" + ')/Items? + "SomeFilterParameters";

//AJAX CALL HERE//
.done(
  function (approvedListItems) {
    if (approvedListItems.d.results.length != 0) {
      $.each(approvedListItems.d.results, function (i, col) {
        allJsonData.push(col);//Push into master array
      });
    }//If closed
    dfd.resolve(allJsonData);
  }
);//Done closed
  promises.push(dfd);
});//jQuery Each closed
return $.when.apply($, promises).promise();

/****AJAX-ЗВОНОК****/

getListItems: function(url) {       
  var dfd = $.Deferred();
    $.ajax({
      url: url,
      type: "GET",
      headers: {
        "accept": "application/json;odata=verbose",
      },
    success: function (data) {
      dfd.resolve(data);
    },
    error: function (error) {
      dfd.reject(sender, args, "Error retrieving items");
    }
  });
  return dfd.promise();         
},

person Sid    schedule 05.11.2017    source источник
comment
ajax-вызовы являются асинхронными... следовательно, тот, который вызывается первым, может занять больше времени, в то время как третий запрос будет завершен и помещен в массив... отсюда и неравномерность порядка массива......   -  person Rohit Kumar    schedule 05.11.2017
comment
вы можете просто отсортировать allJsonData в готовом   -  person Rohit Kumar    schedule 05.11.2017
comment
Пожалуйста, покажите нам реальный вызов Ajax. Чтобы предложить вам лучший ответ, нам нужно увидеть и эту часть кода.   -  person jfriend00    schedule 05.11.2017
comment
@RohitasBehera да, мы можем сортировать allJsonData, но пока я избегаю этого, так как это снова массив объектов json.   -  person Sid    schedule 05.11.2017


Ответы (1)


Я думаю, вы можете сделать что-то простое:

var sortedArray = [AList, BList, CList, DList];

Promise.all(sortedArray.map(function(value) {
    var url = ...;
    return getListItems(url);
})).then(function(results) {
    // results is an array of results from AList, BList, CList, DList in order
    let allJsonData = [];
    results.forEach(function(approvedListItems) {
        allJsonData.push.apply(allJsonData, approvedListItems.d.results);
    });
    // process allJsonData here
});

// simplify getListItems like this
getListItems: function(url) {       
    return $.ajax({
        url: url,
        type: "GET",
        headers: {
            "accept": "application/json;odata=verbose",
        }
    });
},

Общая идея здесь заключается в том, что вы получаете необработанный список (без обработки промежуточных результатов внутри него) для каждого из элементов в sortedArray. Используя либо Promise.all(), либо $.when(), вы получите необработанные списки по порядку. Затем, когда у вас есть все необработанные списки, вы можете обработать их по порядку и построить свою структуру allJsonData по порядку.

Кроме того, вы можете удалить антишаблон обещания из getListItems(). $.ajax() уже возвращает обещание, поэтому нет необходимости заключать его в другое обещание.

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

Кроме того, что-то не так с синтаксисом строки Javascript в вашей переменной url. Я не знаю, что вы намеревались там сделать, поэтому я не уверен, что предложить, но вам нужно исправить и это.

person jfriend00    schedule 05.11.2017
comment
Огромное спасибо jfriend00. Он работает, как и ожидалось. Было бы очень полезно, если бы вы предоставили мне несколько хороших статей/ссылок, связанных с отложенным и обещанием. - person Sid; 06.11.2017
comment
@Sid — вы можете начать читать здесь: developer.mozilla .org/en-US/docs/Web/JavaScript/Reference/. В Google можно найти много хороших статей о обещаниях. Если это ответило на ваш вопрос, вы можете указать это сообществу, щелкнув галочку слева от ответа, и это также принесет вам здесь несколько очков репутации за соблюдение надлежащей процедуры. - person jfriend00; 06.11.2017