Как бы я использовал объект jQuery.Deferred для ожидания завершения асинхронного вызова функции? - PullRequest
4 голосов
/ 08 февраля 2011

Я использую Загрузчик файлов Plupload в форме.Я хочу настроить его так, чтобы при отправке формы, то есть при нажатии кнопки «Отправить», первое, что происходит, - это загрузка файла с последующей отправкой формы.

Из того, что ямогу сказать, и я могу ошибаться, но кажется, что uploader.start() - это асинхронный вызов функции.Таким образом, в данный момент загрузка начнется, и форма будет отправлена ​​до загрузки файлов.Проблема в том, что я не могу контролировать этот вызов функции.

Я недавно читал о новой версии jQuery 1.5 и новом отложенном объекте и кажется, что это может помочь мне решить эту проблему.Есть ли способ дождаться завершения асинхронного вызова функции и продолжить выполнение кода после вызова.Итак, я ищу что-то вроде следующего псевдокода ...

var uploader = $('#plupload_container').pluploadQueue();

$('#submitButton').click(function() {

   // if there are files to be uploaded, do it
   if (uploader.files.length > 0) {

      // make the call and wait for the uploader to finish
      uploader.start();
      while ( the uploading is not done ) {
         wait for the uploader to finish
      }

      // continue with submission
   }
});

Есть ли способ "дождаться" завершения uploader.start(), по сути, ставя паузу на обработчик события click, чтобысначала можно загрузить все файлы, а затем завершить выполнение остальной части обработчика события click?Я пробовал следующее, но «готово» печатается до завершения загрузки файлов ...

$.when(uploader.start()).then(function () {
   console.log("done")
});

Еще одна полезная информация ... Я могу связать определенные события с этим uploader экземпляром объектанапример «UploadProgress» или «UploadComplete».Могу ли я как-то использовать отложенный объект, чтобы перехватить, например, событие «UploadComplete»?Есть ли AJAX-у способ сделать это?

Спасибо.

Ответы [ 3 ]

5 голосов
/ 09 февраля 2011

Ваша проблема в том, что хотя uploader.start делает что-то асинхронное, чтобы код работал, uploader.start должен возвращать объект jquery $.deferred.

Из последнего источника в вашем плагине загрузчика:

/**
 * Starts uploading the queued files.
 *
 * @method start
 */
start : function() {
    if (this.state != plupload.STARTED) {
        this.state = plupload.STARTED;
        this.trigger("StateChanged");
        uploadNext.call(this);
    }
},

Таким образом, он не возвращает отложенный объект.Вместо этого в функции uploadNext есть строка кода:

this.trigger("UploadComplete", files);

Так что нам просто нужно привязать к вашему загрузчику

uploader.bind("UploadComplete", function(files) {
    // your code
});

I 'Мы никогда не использовали этот плагин, но этот должен работать.Удачи.

Если вам нужно использовать deferreds, то вы всегда можете использовать что-то вроде этого псевдокода:

var uploader = $('#plupload_container').pluploadQueue();
var def = $.Deferred();
uploader.bind("UploadComplete", function(files) {
    def.resolve(files);
});
$('#submitButton').click(function() {
   if (uploader.files.length > 0) {
      uploader.start();

      def.done(function(files) {
          def = $.Deferred(); // reset the deferred object.
          // rest of your click handler.
      });

   }
});
3 голосов
/ 07 апреля 2012

В контексте воображаемой сессии загрузки:

var files = ["file1.txt", "file2.txt", "file3.txt"];

Это файлы, которые мы хотели бы загрузить. Давайте соберем еще один массив, в котором для каждой загрузки есть отложенный объект:

var uploads = files.map(upload_one);

Мы вызываем $ .when () с этим массивом отложенных объектов, а также указываем, что делать после каждой загрузки, когда что-то не получается и когда все сделано полностью:

$.when(uploads)
  .progress(function() {
    // report to user, step progress bar, etc
  })
  .fail(function() {
    // display error
  })
  .done(function() {
    // all uploads finished, do stuff
  });

Это рабочая функция для каждой отдельной загрузки. Он возвращает отложенный объект, а также вызывает функции успеха или ошибки в ответ на отдельную загрузку:

function upload_one(file) {
  var deferred = new $.Deferred();
  // start upload

  // if finished:
  deferred.notify();
  deferred.resolve();

  // if failed:
  deferred.reject();

  return deferred;
}
0 голосов
/ 08 февраля 2011

Да.Смысл новой задержки jquery в API ajax - позволить вашему коду ждать другого асинхронного кода.

Если у вас есть несколько асинхронных вызовов, которые зависят друг от друга, отложенный вызов позволит вам выполнить некоторые действия после их завершения.Та же идея применима и здесь.

...