WinJS Promise based file upload queue

2019-09-01 06:16发布

问题:

Scenario

I need a background upload queue that sends files to a server. The queue should send the files in sequential order as they are pushed into the queue (FIFO).

My solution

var pendingFiles = [];
var filesOperation = null;

uploadNextAsync = function(file) {
  var next;
  if (!pendingFiles.length) {
    return WinJS.Promise.as();
  }
  next = pendingFiles.shift();
  fileslogger.debug("Uploading " + next);
  return fileQuery.folder.getFileAsync(next).then(function(file) {
    return Server.sendFileAsync(file).then(function() {
      return filesOk += 1;
    }, function(error) {
      filesNok += 1;
      return logger.error(error.message, error);
    }).then(function() {
      if (pendingFiles.length) {
        return uploadNextAsync(inspection);
      }
    });
  });
};

createTaskForFile = function(file) {
  if (pendingFiles.length == 0) {
    pendingFiles = [file.name]
    filesOperation = uploadNextAsync(file);
  } else {
    pendingFiles.push(file.name);
    return filesOperation.then(function() {
      return uploadNextAsync(file);
    });
  }
};

Problem

It seems that sometimes if createTaskForFile is called very quickly in succession then 2 files end up being uploaded at the same time. So somewhere is a little glitch either in the createTastForFile function on how it uses the fileOperation.then construct or inside the uploadNextAsync does something wrong?

回答1:

Your problem is that pendingFiles is always empty. In createTaskForFile, you would set it to an one-element array then, but immediately call uploadNextAsync() which shifts it out. I guess your script might work if you shifted the file after the file has been uploaded.

However, you actually don't need this array. You can just queue the action to filesOperation, which would be a promise representing the upload of all current files.

var filesOperation = WinJS.Promise.as();
function createTaskForFile(file) {
  return filesOperation = filesOperation.then(function() {
    return uploadNextAsync(file);
  });
}

function uploadAsync(next) {
  fileslogger.debug("Uploading " + next.name);
  return fileQuery.folder.getFileAsync(next.name).then(function(file) {
    return Server.sendFileAsync(file);
  }).then(function() {
    return filesOk += 1;
  }, function(error) {
    filesNok += 1;
    return logger.error(error.message, error);
  });
}