complex asynchronous code becomes simpler
OK, now let's write some actual code. Suppose we want to: Display a load indicator icon to load the JSON of a novel containing the novel's name and the URL of each chapter's content. Fill the page with a novel name load all Chapter body add Chapter body to page stop loading instructions
...... In this process, if there is any error to notify the user, and the load instructions to stop, otherwise it will keep turning down, it is Ching, or bad interface or something.
Of course, you don't have to use JavaScript to show an article so cumbersome that it's much faster to output HTML directly, but this process is a very typical API request pattern: Get multiple data and do something when they're all done.
First, take care of the steps to load data from the network: use Promise for XMLHttpRequest
As long as backward compatibility is maintained, existing APIs are updated to support Promise,xmlhttprequest as one of the key considerations. But now we're going to write a GET request:
function get (URL) {
//returns a new Promise return
Promise (function (resolve, reject) {//
classic XHR operation
var req = new XMLHttpRequest ();
Req.open (' get ', url);
Req.onload = function () {
//when 404 is occurring and so on) call it
//So check the status code
if (req.status = =) {///
in response text as result, complete this Prom Ise
Resolve (Req.response);
}
else {
//otherwise deny this Promise
///(Provide a meaningful Error object)
reject (Error (Req.statustext))
by the result of the status code;
//Network exception processing method
Req.onerror = function () {
Reject (Error ("Network error"));
The issue request
req.send ();
});
Now you can call it:
Get (' Story.json '). Then (function (response) {
Console.log ("success!", response);
}, Function (Error) {
Console.error ("failed!", error);
Click here to view the code. Now we do not need to knock XMLHttpRequest can directly launch HTTP request, so feel much better, can not see this crazy hump named XMLHttpRequest I will be more happy. Chained Call
The "then" story is not over, you can put these "then" in tandem to modify the results or add more asynchronous operations. Processing of Values
You can make some changes to the results and return a new value:
var promise = new Promise (function (resolve, reject) {
resolve (1);
});
Promise.then (function (val) {
console.log (val);//1 return
val + 2;
}). Then (function (val) {
console.log (val);//3
});
Back to the previous code:
Get (' Story.json '). Then (function (response) {
Console.log ("success!", response);
});
The response received is a plain-text JSON, we can modify the Get function, set Responsetype as JSON to specify the server response format, or fix the problem in the Promise world:
Get (' Story.json '). Then (function (response) {return
json.parse (response);
}). Then (function (response) {
Console.log ("Yey json!", response);
});
Since Json.parse only receives one parameter and returns the result of the conversion, we can also refine it:
Get (' Story.json '). Then (Json.parse). Then (function (response) {
Console.log ("Yey json!", response);
});
Click here to view the code run page, open the console to view the output. In fact, we can write the Getjson function super simple:
function Getjson (URL) {return get
(URL). then (json.parse);
}
Getjson returns a Promise that gets JSON and parses it. asynchronous operation of queues
You can also concatenate "then" in sequence to perform an asynchronous operation.
When you return from the "then" callback function, there is a little magic here. If you return a value, it is passed to the next "then" callback, and if you return to a "class Promise" object, the next "then" will wait for the Promise to end explicitly (success/failure) before it is executed. For example:
Getjson (' Story.json '). Then (function (story) {return
Getjson (story.chapterurls[0));
Then (function (chapter1) {
Console.log ("Got Chapter 1!", chapter1);
});
Here we initiate an asynchronous request for "Story.json", return to us with more URLs, and then we'll ask for the first one. Promise first showed the superiority of the event callback. You can even write a separate function that captures the contents of a chapter:
var storypromise;
function Getchapter (i) {
storypromise = storypromise | | Getjson (' Story.json ');
Return Storypromise.then (function (story) {return
Getjson (Story.chapterurls[i]);
})
}
It is very simple to use:
getchapter (0). Then (function (chapter) {
Console.log (chapter);
return Getchapter (1);
}). Then (function (chapter) {
Console.log (chapter);
});
We don't load Story.json until the first getchapter, and then each time Getchapter can reuse the story Promise that has been loaded, so story.json only needs to ask once. Promise is great. Error Handling
As has been seen before, "then" accepts two parameters, one processing succeeds, one processing failure (or affirmative and negative, in Promise terms):
Get (' Story.json '). Then (function (response) {
Console.log ("success!", response);
}, Function (Error) {
Console.log ("failed!", error);
You can also use "catch":
Get (' Story.json '). Then (function (response) {
Console.log ("success!", response);
}). catch (function (error) {
console.log ("failed!", error);
});
There is nothing special about the catch, just the then (Undefined, func) of the grammatical icing, more intuitive. Note that the above two pieces of code behave not only the same, but the latter equivalent:
Get (' Story.json '). Then (function (response) {
Console.log ("success!", response);
}). Then (Undefined, function (error) {
console.log ("failed!", error);
});
The difference is small, but the meaning is extraordinary. When Promise is denied, it jumps to the first then (or catch, the same) that is configured with a negative callback. For then (FUNC1, Func2), one of func1 or FUNC2 will be invoked, but not both. And then (FUNC1). catch (FUNC2) FUNC2 will also be invoked if func1 returns negative, because they are two steps independent of a chained call. Look at the following code: