Как я могу использовать обещания jQuery в пользовательских асинхронных функциях?

#javascript #jquery #backbone.js

#javascript #jquery #backbone.js

Вопрос:

Итак, я создал объект api, который может быть включен в любой файл JavaScript через require.js . В объекте api у меня есть вызовы для создания базовых моделей / коллекций, подобных показанной ниже:

 getDatapoints: function(attributes, callback) {
    require(['models/datapoint'], function(Datapoint){
        var datapoint = new Datapoint.DatapointCollection(attributes);
        datapoint.fetch({success: function(data){
            return callback(data.toJSON());
        }});
    });
}
 

Я хочу иметь возможность запускать несколько вызовов и запускать функцию обратного вызова после завершения ВСЕХ вызовов. Похоже, функция jQuery $.when делает то, что я хочу, но я не уверен, как заставить ее работать с чем-либо, кроме вызовов $.ajax.

Я смотрю в нужном месте? Должен ли я смотреть на что-то вроде q.js?

Комментарии:

1. я не понимаю, как помогут обещания. разве они не предназначены для выполнения большого количества задач в одном процессе? кажется, это больше похоже на выполнение одной вещи для многих процессов. а именно, не будут ли обещания jQuery вызывать каскад сетевой активности при одновременной загрузке многих?

2. @dandavis не обязательно. $.when.apply($, [fetch1(), fetch2(), fetch3()]).done(dostuff) будет получать 1, 2 и 3 одновременно, а затем, когда все три будут завершены, dostuff . Для этого просто потребуется заставить getDatapoints возвращать обещание, например, с обоими текущими ответами.

3. @KevinB правильно, мой ответ точно показывает, как это сделать.

4. @KevinB: хорошая информация и идея об использовании apply().

Ответ №1:

Расширяя ответ @mattacular:

 API = {
  getDatapoints: function (attributes){ 
    var dfd = $.Deferred();
    require(['models/datapoint'], function(Datapoint){
      var dataPoints = new Datapoint.DatapointCollection(attributes);
      dataPoints.fetch().then(function (points){
        dfd.resolve(points.toJSON());
      }, function (error){
        dfd.reject(error);
      });
    });
    return dfd.promise();
  },
  getAllDatapoints: function (arrayOfAttributes){
    var arrayOfPromises = arrayOfAttributes.map(this.getDatapoints);
    return $.when.apply($, arrayOfPromises);
  }
}
 

И где вы на самом деле вызываете getAllDatapoints метод:

 var allDatapointAttributes = [{...}, {...}, {...}];
API.getAllDatapoints(allDatapointAttributes).done(function(){
  console.log.apply(console, arguments);
  // should output an array of arrays containing dataPoint
  // objects when all the requests have completed successfully.
});
 

Ответ №2:

Вы можете сделать это с помощью отложенного объекта jQuery. Вот краткий пример:

 getDatapoints: function (attributes, callback() { 
   var dataPoints = $.Deferred();

   // perform async calls here
   // when "done," call dataPoints.resolve() or dataPoints.reject() accordingly

   return dataPoints.promise();
}
 

редактировать: удален устаревший учебник

Комментарии:

1. Статья, на которую вы ссылались, довольно старая (почти три года). В нем упоминается $.Deferred#pipe() то, что, по моему мнению, либо устарело, либо вообще исчезло. Вместо этого вы должны использовать $.Deferred#then() .

2. Да, извините, это старая закладка, которую я вытащил. Он устарел. Если у вас есть лучшая ссылка, я отредактирую свой ответ, но кто-то другой уже разработал другой ответ, поэтому, вероятно, в этом нет необходимости.