1

Let' say I need to make a synchronous upload of files. One after another. I found this stackoverflow topic. And modified the code:

var arr = ["file1", "file2", "file3"];

var d = $.Deferred().resolve();
while (arr.length > 0) {
   d = d.then(uploadFile(arr.shift()));
}

function uploadFile(file){
    var d = $.Deferred();    
    setTimeout(function(){ console.log("Uploading file:"+file); d.resolve(""); },1000);
    return d.promise();
}

But i still get them all called asynchronously, but with timeout 1000.

Here is fiddle: fiddle

SOLUTION: Big thanx to Felix. Here is working fiddle

Community
  • 1
  • 1
vadimv82
  • 93
  • 1
  • 9

1 Answers1

1

You have to pass a function to .then. Currently you are calling uploadFile immediately inside the loop and passing a promise to .then instead of a function.

You can do the following without having to use a loop:

d.then(function next() {
  var promise = uploadFile(arr.shift());
  return arr.length === 0 ? promise : promise.then(next);
});

This uses indirect recursion instead of a loop.

Felix Kling
  • 795,719
  • 175
  • 1,089
  • 1,143
  • I haven't done much (if any) deferring with jQuery. Would the following also work? `d.then(function() { uploadFile(arr.shift()) });` if redefining the upload by removing the promise (`function uploadFile(file) { console.log("Uploading file:" + file); }`)? – vol7ron May 31 '16 at 14:15
  • Or, I suppose the promise is necessary for the synchronicity – vol7ron May 31 '16 at 14:16
  • *"I suppose the promise is necessary for the synchronicity"* Yes. Without that it wouldn't wait for the timeout. Also, if your code was still inside the loop, the loop would never terminate because the `arr.shift()` happens *inside* the callback and thus `arr.length` would never become smaller. – Felix Kling May 31 '16 at 14:17
  • Reading up on: https://abdulapopoola.com/2014/12/12/the-differences-between-jquery-deferreds-and-the-promisesa-spec/ -- cool stuff. I think my new interest in life is to take a break from a language and then revisit them to see what I've forgotten or never learned :) tbh, I've been doing less jQuery and more React/ES6-only lately – vol7ron May 31 '16 at 14:19