Six options for asynchronous JavaScript programming
- The callback function
- Event listeners
- Event publish/subscribe pattern
- Promise
- Generator Generators/ yield
- async/await
Callback -> Promise -> Generator -> async/await
Promise object
What is the Promise
A promise is a solution to asynchronous programming that holds asynchronous operations internally and allows you to get messages for those asynchronous operations
The characteristics of
- The state of an object is unaffected by external influences. There are three states. We’re in progress
pending
And has been successfullyfulfilled
, has failedrejected
. Only the result of an asynchronous operation can determine the current state, and no other operation can change the state. - Once the state changes, it never changes again, and you can get this result at any time. There are only two possible state changes: from
pending
intofulfilled
And from thepending
intorejected
. When the state is frozen, it’s calledresolved
Have to finalize the design.
Advantages: unified interface, make control asynchronous operation convenient; Solve callback hell by presenting asynchronous operations as synchronous operations
Disadvantages: midway can not be cancelled, once the new execution immediately; An internal error cannot be reflected externally (without a callback function). Pending is a state where you can’t know exactly where you’re going
New Promise(request 1).then(request 2).then(request 3).then(request 4).then(request 5).catch(handle exception)Copy the code
Basic usage
Step 1, createPromise
The instance
const promise = new Promise(function(resolve, reject) {
// ... some code
ifResolve (value); }else{ reject(error); }}); Resolve () changes the pending state to resolved, reject() changes the Pending state to Rejected, reject() changes the pending state to Rejected, and reject() changes the pending state to Rejected.Copy the code
Second, specify the callback function
promise.then(function(value) {
// success
}, function(error) {
// failure
});
thenA method can take two callback functions as arguments. The first callback is called when the Promise object's state changes to Resolved. The second callback is called when the Promise object's state changes to Rejected.Copy the code
The Promise is executed immediately after it is created
The code created internally by the Promise executes immediately, the callback function is put into the task queue, and the tasks in the call stack (i.e., synchronization tasks) are not executed until all the tasks in the task queue are completed.
let promise = new Promise(function(resolve, reject) {
console.log('Promise');
resolve();
});
promise.then(function() {
console.log('resolved.');
});
console.log('Hi! '); // Promise // Hi! // resolvedCopy the code
Promises are typically created as returns from functions, so they can be wrapped and used multiple times in different situations
Ajax operations implemented with Promise objects
const getJSON = function(url) {
const promise = new Promise(function(resolve, reject){
const handler = function() {
if(this.readyState ! = = 4) {return;
}
if (this.status === 200) {
resolve(this.response);
} else{ reject(new Error(this.statusText)); }}; const client = new XMLHttpRequest(); client.open("GET", url);
client.onreadystatechange = handler;
client.responseType = "json";
client.setRequestHeader("Accept"."application/json");
client.send();
});
return promise;
};
getJSON("/posts.json").then(function(json) {
console.log('Contents: ' + json);
}, function(error) {
console.error('Wrong', error);
});
Copy the code
whenresolve()
orreject()
The argument is the other onePromise
Instance when the originalPromise
Status invalid by newPromise
The state determines the originalPromise
The callback function executes
const p1 = new Promise(function (resolve, reject) {
setTimeout(() => reject(new Error('fail')), 3000)
})
const p2 = new Promise(function (resolve, reject) {
setTimeout(() => resolve(p1), 1000) }) p2 .then(result => console.log(result)) .catch(error => console.log(error)) // Error: Fail analysis is as follows: P1 will enter the Rejected state in three seconds, and P2 will enter the Resolved state in one second. As P1 is set to P1, the P2 state will become invalid in one second. P1 is still in the pending state. The p2 state also changes to Rejected, which triggers the callback. Catch () and prints out the parameters in P1 reject()Copy the code
Calling resolve or Reject does not terminate the execution of the Promise’s argument function
new Promise((resolve, reject) => { resolve(1); console.log(2); }).then(r => { console.log(r); }); / / / 1/2Copy the code
And you just put a return in front of it
new Promise((resolve, reject) => {
returnresolve(1); // The following statement does not execute console.log(2); })Copy the code
Promise.prototype
Promise.prototype.then()
parameter
The first argument is the Callback from the Resolved state and the second (optional) is the callback from the Rejected state.
The return value
The then method returns a new Promise instance (note, not the original Promise instance).
So you can write it chained, where a then method is followed by another THEN method.
The chain operation
After the first callback completes, the second callback is passed the result as an argument.
getJSON("/posts.json").then(function(json) {
return json.post;
}).then(function(post) {
// ...
});
Copy the code
The former callback returns a Promise object (that is, an asynchronous operation), while the latter waits for the state of the Promise object to change before being called.
getJSON("/post/1.json").then(
post => getJSON(post.commentURL)
).then(
comments => console.log("resolved: ", comments),
err => console.log("rejected: ", err)
);
Copy the code
Promise.prototype.catch()
Promise.prototype. Catch equivalent to. Then (null, rejection) or. Then (undefined, rejection).
Suggest using.catch()
without.then()
To catch errors
Because.catch() not only handles the state of the Promise object rejected, but also catches errors in the.then() method
getJSON('/posts.json').then(function(posts) {
// ...
}).catch(function(error) {// Handle getJSON and an error that occurred while the previous callback function was running console.log('Error! ', error);
});
Copy the code
If the Promise state has changed to Resolved, throwing an error is invalid
Errors in the Promise object are “bubbling” and are passed backwards until they are caught
getJSON('/post/1.json').then(function(post) {
return getJSON(post.commentURL);
}).then(function(comments) {
// some code
}).catch(function(error) {// Handle the first three Promise errors});Copy the code
Promises eat up mistakes
The Promise definition displays syntax errors on the console, but the code does not stop running and continues to execute, meaning that errors inside a Promise do not affect code outside the Promise
const someAsyncThing = function() {
return new Promise(function(resolve, reject) {// The following line is an error because x does not declare resolve(x + 2); }); }; someAsyncThing().then(function() {
console.log('everything is great');
});
setTimeout(() => { console.log(123) }, 2000);
// Uncaught (in promise) ReferenceError: x is not defined
// 123
Copy the code
The return value is also onePromise
Object, which can be chain-operated
const someAsyncThing = function() {
return new Promise(function(resolve, reject) {// The following line is an error because x does not declare resolve(x + 2); }); }; someAsyncThing() .catch(function(error) {
console.log('oh no', error);
})
.then(function() {
console.log('carry on'); }); // oh no [ReferenceError: x is not defined] // Carry on if no error is reported, the catch method is skippedCopy the code
Promise.prototype.finally()
The finally method is used to specify actions that will be performed regardless of the final state of the Promise object.
Callbacks specified by the finally method are also executed after the callbacks specified by then or catch.
Promise. Then (result = > {...}). The catch (error = > {...}), finally (() = > {...});Copy the code
The callback function takes no arguments
Unable to determine the state, in order to write less of the same code.
implementation
Promise.prototype.finally = function (callback) {
let P = this.constructor;
return this.then(
value => P.resolve(callback()).then(() => value),
reason => P.resolve(callback()).then(() => { throw reason })
);
};
Copy the code
The return value is always the original value
// use undefined promise.resolve (2). Then (() => {}, () => {}) // use undefined promise.reject ().reject() => {}). Then () => {}, () = > {}) / / reject a value of 3 Promise. Reject (3) finally (() = > {})Copy the code
Promise method
Promise.all()
Effect: Wrap multiple Promise instances into a new Promise instance
Const p = promise. all([p1, p2, p3]);
Parameters: Enter an array whose elements are not Promise instances and will be converted to promise.resolve
Return value: Returns a new Promise instance with the state of P determined by P1, P2, and P3
- Only when the states of P1, P2 and P3 become depressing, the state of P will become depressing. At this time, the return values of P1, P2 and P3 will form an array and be passed to the callback function of P.
- If p1, P2, and P3 are rejected, P becomes rejected, and the return value of the first rejected instance is passed to p’s callback function.
- If a Promise instance that is a parameter defines its own catch method, then it does not fire the promise.all () catch method once it is rejected.
Conclusion: logic and whole pity only pity, a rejected
const p1 = new Promise((resolve, reject) => {
resolve('hello');
})
.then(result => result)
.catch(e => e);
const p2 = new Promise((resolve, reject) => {
throw new Error('Error reported'); }) .then(result => result) .catch(e => e); Promise.all([p1, p2]) .then(result => console.log(result)) .catch(e => console.log(e)); / / /"hello", Error: Error]Copy the code
Promise.race()
const p = Promise.race([p1, p2, p3]);
In the above code, the state of P changes as long as one of the first instances of P1, P2, and P3 changes state.
The return value of the first changed Promise instance is passed to p’s callback.
Conclusion: race, whoever returns first returns this value
// Change the state of a Promise to REJECT or resolve if no result is obtained within a specified time. const p = Promise.race([ fetch('/resource-that-may-take-a-while'),
new Promise(function (resolve, reject) {
setTimeout(() => reject(new Error('request timeout')), 5000)})]); p .then(console.log) .catch(console.error);Copy the code
Promise.allSettled()
The wrapper instance will not complete until all of these parameter instances return the result, whether this is fulfilled or Rejected.
The new Promise instance is returned, and once it is over, the state is always fulfilled
Conclusion: All are set up to resolve promise.all () without knowing that all operations are finished
const resolved = Promise.resolve(42);
const rejected = Promise.reject(-1);
const allSettledPromise = Promise.allSettled([resolved, rejected]);
allSettledPromise.then(function (results) {
console.log(results);
});
// [
// { status: 'fulfilled', value: 42 },
// { status: 'rejected', reason: -1 }
// ]
Copy the code
The listener receives an array results as an argument.
Each member of this array is an object corresponding to two Promise instances passed in promise.allSettled ().
Each object has a status attribute, whose value can only be the string fulfilled or the string Rejected.
Someday, the object has the value attribute, and the object has the reason attribute, which corresponds to the return values of the two states.
Promise.any()
The promise.any () method takes a set of Promise instances as parameters and wraps them into a new Promise instance.
As long as one parameter instance becomes a depressing state, the packaging instance will become a depressing state. If all parameter instances become the Rejected state, the wrapper instance becomes the Rejected state.
This is a big pity, which is a pity only once in a lifetime
var resolved = Promise.resolve(42);
var rejected = Promise.reject(-1);
var alsoRejected = Promise.reject(Infinity);
Promise.any([resolved, rejected, alsoRejected]).then(function (result) {
console.log(result); // 42
});
Promise.any([rejected, alsoRejected]).catch(function (results) {
console.log(results); // [-1, Infinity]
});
Copy the code
Promise.resolve()
Effect: Turn an existing object into a Promise object
Grammar:
Promise.resolve('foo'New Promise(resolve => resolve();'foo'))
Copy the code
Parameters:
(1) The argument is an instance of Promise
Promise.resolve will return the instance intact without any modifications.
(2) The argument is a Thenable object
The promise. resolve method converts this object to a Promise, and then immediately executes the thenable object’s then method.
let thenable = {
then: function(resolve, reject) { resolve(42); }};let p1 = Promise.resolve(thenable);
p1.then(function(value) {
console.log(value); // 42
});
Copy the code
(3) Arguments are not objects with then methods, or are not objects at all
The promise. resolve method returns a new Promise object in the resolved state as the argument to the callback function.
const p = Promise.resolve('Hello');
p.then(function (s){
console.log(s)
});
// Hello
Copy the code
(4) Without any parameters
Return an Resolved Promise object directly. Pay attention to the order in which the callbacks are executed.
setTimeout(function () {
console.log('three');
}, 0);
Promise.resolve().then(function () {
console.log('two');
});
console.log('one');
// one
// two
// three
Copy the code
Promise.reject()
Returns a new Promise instance with the status Rejected.
The arguments of the promise.reject () method are left as reject arguments and become arguments for subsequent methods.
const p = Promise.reject('Wrong'); // const p = new Promise((resolve, reject) => reject('Wrong'))
p.then(null, function(s) { console.log(s) }); / / make a mistakeCopy the code
Promise.try()
Let synchronous functions execute synchronously, asynchronous functions execute asynchronously, and let them have a uniform API
The following function f() represents operations that are not determined to be synchronous or asynchronous
// const f = () => console.log()'now');
(
() => new Promise(
resolve => resolve(f())
)
)();
console.log('next');
// now
// next
Copy the code
// Async () => f())().then(...) .catch(...)Copy the code
Promise.try(() => f()).then(...) .catch(...)Copy the code