asynchronous?
I have seen the word asynchronous (asynchronous) in many places, but I find myself often treated as "already clear" (* ̄? ̄) when I don't quite understand the concept.
If you have a similar situation, it does not matter, search the word, you can get a general description. Here, I'll do a little extra explaining about JavaScript's asynchrony.
Take a look at this piece of code:
var start = new Date ();
settimeout (function () {
var end = new Date ();
Console.log ("Time Elapsed:", End-start, "MS");
while (new Date-start < 1000) {};
This code will get a result like time elapsed:1013ms when it runs. The function that settimeout () is set to execute in the next 500ms is actually waiting for more time than 1000ms to execute.
How do you explain it? When settimeout () is invoked, a deferred event is queued. Then, continue with the code after this, and the code behind it, until there is no code. When there is no code, the JavaScript thread goes into idle, at which point the JavaScript execution engine looks at the queue, finds the "should trigger" event in the queue, and then invokes the processor (function) of the event. After the processor completes, it returns to the queue and then looks at the next event.
single-threaded JavaScript, which works through queues, in the form of event loops. So, in the preceding code, you drag the execution engine up to 1000ms while the code is running, and no events are triggered until all the code runs back to the queue. This is the asynchronous mechanism of JavaScript.
the asynchronous puzzle of JavaScript
Asynchronous operations in JavaScript may not always be straightforward.
Ajax may be the most asynchronous operation we can use. In jquery, for example, the code that initiates an AJAX request is typically this:
Ajax request schematic Code
$.ajax ({
url:url,
data:dataobject,
success:function () {},
error:function () {}
});
Is there any problem with this way of writing? In simple terms, it's not light enough. Why do we have to write success and error callbacks at the place where the request is made? If my callback is going to do a lot of things, do I have to think of something and run back here to add code?
For example, we have to do one thing: There are 4 ajax access to the URL address, you need to first AJAX access to the 1th, after the 1th visit completed, with the returned data received as a parameter to access the 2nd, after the 2nd access is completed and then 3rd ... This is done to 4 full access. In this way, it would seem like this:
$.ajax ({
url:url1,
success:function (data) {
$.ajax ({
url:url2,
data:data,
success: function (data) {
$.ajax ({
//...});}}
)
You must think that this code called Pyramid of Doom (Pyramid Doom) looks bad. Accustomed to the direct addition of a callback, you may feel that this one is passed to the next asynchronous event is impossible to start. Naming and separating these callback functions can reduce nesting in form, making the code clear, but still does not solve the problem.
Another common difficulty is to send two AJAX requests at the same time, and then do one more thing after the two requests are successfully returned, and think about whether it's a bit tricky to just append the callbacks to their respective call locations in the previous way.
Suitable for these asynchronous operations, you can write more elegant code is promise.
Promise play .
What is promise? Let's go ahead and take the AJAX request schematic code in front of jquery as an example, and that code can actually be written like this:
var promise = $.ajax ({
url:url,
data:dataobject
});
Promise.done (function () {});
Promise.fail (function () {});
This is equivalent to the previous AJAX request schematic code. As you can see, the addition of promise makes the code form change. The AJAX request was "saved" as if it were a variable assignment. This is the encapsulation that encapsulates the real meaning of making asynchronous events easier.
Encapsulation is useful
The Promise object is like a encapsulated reference to an asynchronous event. Want to do something after this asynchronous event is done? Attach a callback to it, no matter how many to attach!
The Ajax method of jquery will return a Promise object (this is the feature that the jQuery1.5 focuses on). If I have Do1 (), Do2 () two functions to execute after the asynchronous event completes successfully, only this is necessary:
Promise.done (DO1);
Other code here.
Promise.done (DO2);
This is a lot more free, and I just need to save this promise object and attach any number of callbacks to it at any time of writing code, without having to worry about where the asynchronous event originated. This is the advantage of promise.
A formal introduction
Promise should be so useful for asynchronous operations that it develops a specification for COMMONJS called promises/a. Promise represents the return value after the end of an operation, which has 3 states:
- Affirmative (fulfilled or resolved), indicating that the promise operation was successful.
- Negation (rejected or failed) indicates that the promise operation failed.
- Waiting (pending), has not been confirmed or negative results, in progress.
In addition, there are 1 nominal states used to indicate that promise operations have succeeded or failed, that is, the set of positive and negative states, called the end (settled). Promise also has the following important features:
- A promise can only change from waiting to a positive or negative state once, once converted to a positive or negative state, it will never change the state.
- If you add a callback for success or failure after the end of a promise (success or failure, with the previous description), the callback function executes immediately.
Think about AJAX operations, initiate a request, wait, and then successfully receive a return or an error (failure). Is this quite consistent with promise?
A good example is the further explanation of the Promise feature: jquery $ (document). Ready (Onready). Where the Onready callback function executes when the DOM is ready, but interestingly, if the DOM is ready before executing to this code, then Onready executes immediately without any delay (that is, synchronous).
Promise Sample
Generate Promise
PROMISES/A lists a series of JavaScript libraries that implement promise, and jquery is also in it. Here's the code to generate promise with jquery:
var deferred = $. Deferred ();
Deferred.done (function (message) {Console.log (' Done: ' + message '});
Deferred.resolve ("Morin"); Done:morin
jquery itself deliberately defines a class called deferred, which is actually a promise. $. The Deferred () method returns a newly generated promise instance. On the one hand, use Deferred.done (), Deferred.fail (), etc. for it to attach a callback, on the other hand, invoke Deferred.resolve () or deferred.reject () to affirm or negate this promise, And you can pass arbitrary data to the callback.
Merging Promise
Remember what I said earlier about sending 2 Ajax requests at the same time? Continue with jquery, for example, and promise will be able to solve it this way:
var promise1 = $.ajax (URL1),
promise2 = $.ajax (url2),
promisecombined = $.when (Promise1, promise2);
Promisecombined.done (Ondone);
The $.when () method can combine multiple promise to get a new promise, which is equivalent to establishing an and (logical) relationship between the original multiple promise, and if all of the constituent promise are successful, the merged promise is also successful. If any one of the constituent promise fails, then the merged promise is immediately failed.
Cascade Promise
I'm going to go ahead and do a series of asynchronous tasks sequentially. It will use the promise most important. Then () method (in the PROMISES/A specification, as well as the "object with then () method" to define promise). The code is as follows:
var promise = $.ajax (URL1);
Promise = Promise.then (function (data) {return
$.ajax (url2, data;
});
Promise = Promise.then (function (data) {return
$.ajax (url3, data;
});
// ...
The complete form of the promise. Then () method is. Then (Ondone, Onfail, onprogress), which looks like an easy way to attach a variety of callbacks to a one-time (. done (),. Fail () can be used). Yes, you can do that, and that's the equivalent.
But the. Then () method also has more useful features. As then the word itself, it is used to clearly indicate the context of the asynchronous event: "First this, then (then) again". This is called a cascade of promise.
To Cascade Promise, be aware that in the callback function passed to then (), be sure to return the promise you want to represent the next task (such as the $.ajax (URL2, data) of the above code). In this way, the previously assigned variable will become the new promise. If the callback function for then () returns a promise, the then () method returns the original promise.
You think it's a little hard to understand? From a code execution point of view, the above code with multiple then () is actually run over by the JavaScript engine. But it's like writing a good play, and after reading it, the JavaScript engine arranges the actors to perform according to the script in the future, and the performance is asynchronous. The then () method is to allow you to write the pen for the asynchronous script.
apply promise to the API based on callback functions
The $.ajax () method used repeatedly in the previous article returns a Promise object, which is actually a benefit that jquery specifically provides. The reality is that most JavaScript APIs, including native functions in Node.js, are based on callback functions, rather than on promise. In this case, the use of promise will need to do some processing.
This process is actually relatively simple and straightforward, here is an example:
var deferred = $. Deferred ();
SetTimeout (deferred.resolve, 1000);
Deferred.done (Ondone);
In this way, the promise of positive or negative triggers, as the callback of the API, become the Promise processing mode.
How did the promise come true?
This article writes promise to write here, you discover all is based on already has realized the Promise library. What if you were to build a promise yourself?
The first q in the PROMISES/A library list is the most consistent and fairly intuitive implementation of the PROMISES/A specification. If you want to know how to make a promise, you can refer to the design pattern parsing provided by Q.
Limited to space, this article only introduces the application of promise. I will write a separate article later detailing the implementation details of promise.
ECMAScript 6, a follow-on version of JavaScript, provides promise, and if you want to know its usage, it is recommended to read JavaScript Promises:there and back again.
Conclusion
Promise the word stubborn to not suitable for translation, a glance will feel the meaning of unknown. However, it does provide quite a bit of help when you're doing more complex asynchronous tasks in JavaScript.