How can I use the jQuery.Deferred object to wait for the completion of an asynchronous function call?

I am using the Plupload file downloader in the form. I want to configure it so that when I submit the form, that is, when the "Submit" button is clicked, the first thing that happens is the file upload, followed by the submission of the form.

From what I can say, and I could be wrong in that, but it seems that calling uploader.start() is an asynchronous function call. So, at this point, the download will begin, and the form will be submitted before the files are downloaded. The problem is that I do not control this function call.

I recently read about the new version of jQuery 1.5 and the new Delayed Object , and it looks like this can help me solve this problem. Is there a way to wait for the asynchronous function call to complete its work, and then continue to execute the code after the call. So I'm looking for something like the following pseudo code ...

 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 } }); 

Is there a way to β€œwait” for uploader.start() to complete, essentially pause the click event handler so that all files can be loaded first, and then the rest of the click event handler can finish executing? I tried the following, but the "done" is printed before the files are downloaded ...

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

Another useful information ... I can associate certain events with this instance of the uploader object, for example, "UploadProgress" or "UploadComplete". Can I use the Pending Object anyway to catch when the "UploadComplete" event fires, for example? Is there an AJAX-y way to do this?

Thanks.

+4
source share
3 answers

Your problem is that although uploader.start does something asynchronous for the code to work, uploader.start should return a jquery $.deferred .

From the last source in your plugin to download:

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

Thus, it does not return a pending object. Instead, the uploadNext function has this line of code:

this.trigger("UploadComplete", files);

Therefore, we just need to bind to your bootloader,

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

I have never used this plugin, but this one should work. Good luck.

If you must use deferrals, you can always something like this pseudo-code:

 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. }); } }); 
+5
source

In the context of an imaginary boot session:

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

These are the files we would like to download. Let another array be assembled that has a pending object for each load:

 var uploads = files.map(upload_one); 

We call $ .when () with this array of pending objects, and also indicate what to do after each load, when something fails and when everything is done completely:

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

This function works for each individual download. It returns a pending object, and also calls the success or error functions in response to an individual load:

 function upload_one(file) { var deferred = new $.Deferred(); // start upload // if finished: deferred.notify(); deferred.resolve(); // if failed: deferred.reject(); return deferred; } 
+3
source

Yes. The jquery new point, delayed in ajax api, should let your code wait for another asynchronous code.

If you have several asynchronous calls that are dependent on each other, pending actions will allow you to perform some action after they are completed. The same idea applies here.

-1
source

Source: https://habr.com/ru/post/1338875/


All Articles