0

I am using jQuery v2.1.4, I have the following function which for each object in evt.data.files(the number of element in the array will vary) needs to make a request to a server.

The problem I am facing with this script is that for each element in evt.data.files an asynchronous request is made, instead I need:

  • execute each request in sequence (if possible with jQuery)
  • call a single method when all the request are successfully returned.

Could you please suggest me a solution with an example? Thanks.

options.onInit = function (finder) {
    finder.on('files:choose', function (evt) {
        // files is an array of n object
        evt.data.files.forEach(function (file) {
            // req is an jquery deferred object
            var req = finder.request('command:send', {
                name: 'ImageInfo',
                folder: file.get('folder'),
                params: { fileName: file.get('name') }
            }).done(function (response) {
                if (response.error) {
                    return;
                }

            });
        });
    });
}.bind(this);
rrk
  • 14,861
  • 4
  • 25
  • 41
GibboK
  • 64,078
  • 128
  • 380
  • 620
  • You can chain your .done events. – MartijnK Feb 10 '16 at 12:33
  • 1
    Switch to a promise-based code model. You can then use `.then()` for sequence and `$.when()` for parallel operations (like "all done"). – Gone Coding Feb 10 '16 at 12:34
  • Thanks for commenting, I made an edit, I understand your point but the number of element in evt.data.files is variable – GibboK Feb 10 '16 at 12:34
  • @GoneCodingGoodbye how to pass to $.when() the promises (dynamically create in the forEach), thanks for commenting. – GibboK Feb 10 '16 at 12:38
  • Maybe you can try something like this: [http://stackoverflow.com/a/35056741/5850827](http://stackoverflow.com/a/35056741/5850827) – Fearodin Feb 10 '16 at 12:41
  • Would you be able to provide me example following my original script? Thanks again! – GibboK Feb 10 '16 at 12:42
  • Have a look at [How to sequentially run promises with Q](http://stackoverflow.com/a/18387432/1048572) – Bergi Feb 10 '16 at 12:52
  • The other way would be to create a new promise that you resolve when all other are resolved. For this build an array and push each promise's results in. Then in the then function you test the array length : if it's the same as you're data.files.length, you resolve your promise and pass your array of data. Since javascript is mono-threaded you won't have any concurrency problem. – Walfrat Feb 10 '16 at 13:33
  • Realised my mistake and deleted my first answer. You just need to chain them sequentially using a `promise = promise.then(newpromise)` pattern. The last promise will fire when all are done. Added new answer below. Give it a shot. – Gone Coding Feb 10 '16 at 14:12

1 Answers1

2

I realise I misread the question first time. You only need to run the requests sequentially and await the last one:

Use promise = promise.then(newPromise) to chain promises sequentially:

e.g.

options.onInit = function (finder) {
    finder.on('files:choose', function (evt) {
        var promise = $.when(); // start with a resolved promise

        // files is an array of n object
        evt.data.files.forEach(function (file) {
            promise = promise.then(function(){
               return finder.request('command:send', {
                  name: 'ImageInfo',
                  folder: file.get('folder'),
                  params: { fileName: file.get('name') }
               });
            });
        });
        promise.then(function(){
            alert("Last one done");
        });
    });
}.bind(this);

The key feature here is to return the promise inside an anonymous function in each then call. This defers the execution until the previous promise resolves, but still chains the promises.

GibboK
  • 64,078
  • 128
  • 380
  • 620
Gone Coding
  • 88,305
  • 23
  • 172
  • 188
  • Please guys, add a comment when down-voting. By the way, this answer solved my issue. Thanks for your time on this! – GibboK Feb 10 '16 at 19:57