The Promise pattern of JavaScript asynchronous callbacks encapsulates the instance

  • 2020-03-30 03:17:38
  • OfStack

As web page interactions become more complex, so do asynchronous JavaScript operations. For example, the common ajax request needs to respond to the operation when the request is completed. The request is usually asynchronous, and the user can perform other operations during the request process without blocking the page. This asynchronous interaction effect is quite friendly to the user. However, for developers to deal with this kind of operation in large quantities is not very friendly. The operation completed by the asynchronous request must be predefined in the callback function, which must be called when the request is complete. This kind of non-linear asynchronous programming will make the developers very uncomfortable, but also brings a lot of inconvenience, increasing the degree of coupling and complexity of the code, the organization of the code will be very elegant, greatly reduce the maintainability of the code. The situation is a little more complicated. If an operation has to wait for multiple asynchronous ajax requests to complete, the callback function will be nested, and if you need to nest several layers, you will be lucky.
Take a look at the following common asynchronous function.


var showMsg = function(){
    setTimeout(function(){
        alert( 'hello' );
    }, 5000 );
};

If you want to add a callback to this function, you usually do so.


var showMsg = function( callback ){
    setTimeout(function(){
        alert( 'hello' );
        //Add a callback here
        callback();
    }, 5000 );
};

If you use the promise.js Promise, the method of adding callbacks is much more elegant, provided that you need to wrap the original function into a Promise instance.


var showMsg = function(){
    //Construct a promise instance
    var promise = new E.Promise();

    setTimeout(function(){
        alert( 'hello' );

        //Change the promise state
        promise.resolve( 'done' );
    }, 5000 );

    //Return the promise instance
    return promise;
};

The first step is to construct a promise instance inside the function. The second step is to deploy the function to change the state of the promise to complete. The third step is to return the promise instance. Each promise instance has three states, pending, resolved, and rejected. Now let's see how to add a callback.


showMsg().then(function( str ){
    //Callbacks are added here
    callback( str );
});

This completely separates the callback function from the original asynchronous function, which is much more elegant in terms of the organization of the code. Resolve accepts a parameter that makes it easy to transfer data to a callback added using the then method.
For ajax requests, easy-js simply encapsulates the ajax method as a promise object, and you can simply add the then method and call back.


E.ajax({
    url : 'test1.php',
    type : 'GET'
})
.then(function(){
    //Adds a successful callback to the request
}, function(){
    //Add a callback that failed the request
});

The then method takes two functions, the completed callback and the failed callback, as arguments.
What if you have multiple ajax requests mentioned above? So we're going to use the when method. The method can accept multiple promise instances as parameters.


var requests = E.when(E.ajax({
    url : 'test1.php',
    type : 'GET'
}), E.ajax({
    url : 'test2.php',
    type : 'GET'
}));
requests.then(function( arg1, arg2 ){
    console.log( 'success : ' + arg1[0] + arg2[0] );
}, function( arg1, arg2 ){
    console.log( 'failure : ' + arg1 + arg2  );
});

The when method is to store multiple promise instances in an array, wait until all promise instances in the array are in the completed state, then execute the completed callback. Once an instance is in the rejected state, then execute the rejected callback immediately.

The Promise pattern is one of the CommonJS specifications. Many mainstream JavaScript libraries have implementations, such as jQuery and Dojo, that have Deferred to implement these features. JQuery's Deferred is fun to tease here, but aside from its internal use, it should be one of the least used modules, which has something to do with its more complex use.


Related articles: