Callbacks That Permit Asynchronous Returns

Since 3.4, Fine Uploader has been embracing the concept of “promises” which allow for support of asynchronous tasks. Initially, promises were introduced to allow user input for pasted images for the “paste to upload” feature. Then, in 3.5, Fine Uploader began to make more use of promises internally. For example, the drag and drop modules uses promises to handle the complex web of asynchronous callbacks associated with the Filesystem API. Now, starting with version 3.6, Fine Uploader will allow promises to be valid return types for some callbacks (#805).

Supported Callbacks

Starting with version 3.6, the following callbacks can handle promissory return types. All of these callbacks can also prevent an associated action from being executed with a false return value (non-promise) or a call to failure() on a returned promise instance.

  • onSubmit
  • onCancel
  • onResume
  • onValidateBatch
  • onValidate
  • onSubmitDelete
  • onPasteReceived

Examples and Use Cases

Of couse, you don’t have to return a promise – you can simply return “false” (to prevent the associated action inline), or nothing at all (undefined). However, there are some instances where you may want to perform some asynchronous work in your callback handler. A promise can be returned from any of the above callbacks if you need to execute some non-blocking task, such as an ajax request, or asking the user for input via a modal window that does not block the UI thread (such as a Bootstrap modal, or a Bootbox.js dialog box.

For example, let’s say you want to ask the user (on large files) to confirm a request to cancel an in-progress upload. Your onCancel callback handler might look something like this, assuming use of a Bootbox.js Confirm dialog:

$('#myFineuploader')
  .on("cancel", function(event, id, name){

    var promise = new qq.Promise();

    bootbox.confirm("Cancel " + name + "?", function(result) {
      if (result) {
        promise.success(); //proceed with the cancel request
      }
      else {
        promise.failure(); //don't cancel - ignore
      }

    });

    return promise;

  });

Notice that Fine Uploader waits the user to provide input, after which your code will call either failure() on the promise instance (ignoring the cancel request) or success() (confirming the cancel request). Fine Uploader does not block and other files, or any other UI tasks. It simply defers the work required to cancel the in-progress file until the returned promise is “fulfilled”.

The same confirmation concept can be applied to a onSubmitDelete handler, an onSubmit handler, an onResume handler, or even an onPasteReceived callback handler.
Note that the dialog will NOT pause the in-progress upload. There is no way to reliably pause an in-progress upload, especially cross-browser. This is why I suggest that you only prompt the user for “large”/slow-moving file uploads, and probably only when there is a reasonable amount of time left to upload for the associated file. Otherwise, the upload may complete before the user responds to the dialog.

Another example involves the onSubmit handler. Suppose you want to ask the user for some additional information regarding a submitted item. In this example, let’s use a Bootbox.js prompt dialog.

$('#myFineuploader')
  .on("submit", function(event, id, name) {

    var promise = new qq.Promise(),
        self = this;

    bootbox.prompt("Enter a description for this item", function(description) {
      if (description === null) {
        promise.failure(); //the user cancelled the dialog, so, prevent this item from being submitted
      }
      else {
        $(self).fineUploader('setParams', {description: description}, id);
        promise.success(); //proceed with processing of this item
      }

    });

    return promise;
  });

Here, you are asking the user to describe the submitted item. The answers to this prompt will be sent as a parameter along with the item in the associated upload POST request.

Note that this callback will be invoked for each submitted file, so, if you plan on handling multiple submissions at once (via drag and drop or multiple selection in the file chooser), you will want to maintain a queue of promise instances created in your callback handler invocations and present the user with dialogs for each submitted item one at a time. You can add a new promise instance along with appropriate context (file name and ID) with each callback invocation, and continue to solicit the user to input a description for each submitted file until your queue of promise instances is empty. Don’t forget to fulfill each promise after the user provides feedback!

I hope you find this enhancement useful. If you have any other ideas/requests for further enhancements or features, please file a feature request in the project’s issue tracker.

regards,

-Ray Nicholus and the rest of the Fine Uploader team @ Widen Enterprises