Angular JS — $q.all() отслеживает индивидуальный прогресс загрузки

Я использую модуль angular-file-upload от danialfarid (https://github.com/danialfarid/angular-file-upload), и это прекрасно работает.

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

Однако я не могу правильно идентифицировать отдельные изображения, которые я загружаю, потому что идентификатор файла постоянно изменяется циклом for.

      uploadPhotos: function (files) {

        var deferred = $q.defer()
        var queue = []

        for (var i = 0; i < files.length; i++) {
          var file = files[i];
          var up = $upload.upload({
            url: locationURI +'/photos',
            file: file,
            fileFormDataName: 'image'
          }).then(
            function (data) {
              console.log(data)
            },
            function (err) {
              console.log(err)
            },
            function(evt) {
              // progress events
              console.log('percent: ' + parseInt(100.0 * evt.loaded / evt.total));
            }
          )
          queue.push(up)
        }

        $q.all(queue).then(
          function (data) {
            deferred.resolve(data)
          },
          function (err) {
            deferred.reject(err)
          }
        )

        return deferred.promise
      }

Это, без всякого удивления, запутанный вывод, который я получаю:

    percent: 68 restfactory.js:359
    percent: 100 restfactory.js:359
    percent: 100 restfactory.js:359
    percent: 14 restfactory.js:359
    percent: 37 restfactory.js:359
    percent: 52 restfactory.js:359
    percent: 89 restfactory.js:359
    percent: 100 restfactory.js:359
    percent: 100 restfactory.js:359

У вас есть идеи, как мне удалось получить что-то вроде:

    file1 - percent: 68 restfactory.js:359
    file1 - percent: 100 restfactory.js:359
    file2 - percent: 100 restfactory.js:359

person domokun    schedule 10.06.2014    source источник


Ответы (1)


Замыкания внутри циклов сложны. Закрытие переменной цикла всегда будет получать последнее значение (например, см. этот вопрос - и погуглите, чтобы узнать больше теории/деталей). Что вы хотите, так это вызвать другую функцию внутри цикла:

for (var i = 0; i < files.length; i++) {
    var up = doTheUpload(files[i]);
    queue.push(up);
}

И doTheUpload() содержит исходный код, возвращающий обещание и использующий правильный fileне знаю API, я предполагаю, что file.name содержит имя файла; отрегулируйте соответствующим образом):

function doTheUpload(file) {
      var up = $upload.upload({
        url: locationURI +'/photos',
        file: file,
        fileFormDataName: 'image'
      }).then(
        function (data) {
          console.log(data)
        },
        function (err) {
          console.log(err)
        },
        function(evt) {
          // progress events
          console.log(file.name + ' percent: ' + parseInt(100.0 * evt.loaded / evt.total));
        }
      );
      return up;
}
person Nikos Paraskevopoulos    schedule 10.06.2014
comment
Только что написал, опередил ;) - person maurycy; 10.06.2014
comment
Черт, это было легко. Думаю, сегодня я наконец-то узнал кое-что о замыканиях! - person domokun; 10.06.2014