The characteristics of
1. The status of the object is not affected by the outside world.
There are three states:Pending
,This is a big pity.
andRejected (failed)
Only the result of an asynchronous operation can determine the current state, and no other operation can change the state.
2. Once the state changes, thenWon't change
You can get this at any time.
There are only two possibilities for state change: frompending
intofulfilled
And from thepending
intorejected
Promise shortcomings
1. Unable to cancelPromise
Once,new
It would beExecuted immediately
Can’t cancel midway
2. If the callback function is not set,Promise
Errors thrown internally are not reflected externally
3, when inpending
State, you cannot know the current progress stage
As long as the two things happen, which is very disappointing and rejected, the state will be frozen and will never change again. This is called resolved.
If the change has already occurred, adding a callback to the Promise object will get the same result immediately.
The event was characterized by:
If you miss it, listen again. YesGet no results
the
Promises are completely different from events
Basic usage
Promise is a constructor
1, const promise = new promise (function(resolve, reject) {});
2,new Promise
Returns aPromise object
, receive aExcutor function
As a parameter
3,excutor
There are twoFunction types
parameterResolve (success), reject (failure)
The second function is optional and does not have to be provided
const promise = new Promise(function(resolve, reject) {
// ... some code
if (/* Asynchronous operation succeeded */){
resolve(value);
} else{ reject(error); }});Copy the code
4,Promise
After the instance is generated, you can usethen
Methods specified separatelyresolved
State andrejected
The state of theThe callback function
.
var _promise = new Promise(function(resolve, reject){
setTimeout(function(){
var rand = Math.random();
if(rand<0.5){
resolve("resolve" + rand);
}else{
reject("reject"+ rand); }},1000);
});
_promise.then(result= > { // onFulfilled
console.log(result); // 'fulfilled'
}).catch(reason= > { // onRejected will not be called
console.log(reason)
})
Copy the code
5. Promise will be executed immediately after it is created
Promise is executed immediately after a new Promise is created, so “Promise” is printed first.
then
The callback function specified by theThe synchronization task is executed only after all synchronization tasks in the current script are completed
, soresolved
The final output
let promise = new Promise(function(resolve, reject) {
console.log('Promise');
resolve();
});
promise.then(function() {
console.log('resolved.');
});
console.log('Hi! ');
// Promise
// Hi!
// resolved
Copy the code
Asynchronously loading images
function loadImageAsync(url) {
return new Promise(function(resolve, reject) {
const image = new Image();
image.onload = function() {
resolve(image);
};
image.onerror = function() {
reject(new Error('Could not load image at ' + url));
};
image.src = url;
});
}
Copy the code
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
The argument to the resolve function may be another Promise instance in addition to the normal value
The result of an asynchronous operation is the return of another asynchronous operation
const p1 = new Promise(function (resolve, reject) {
console.log(3)
setTimeout(() = > reject(new Error('fail')), 3000)})const p2 = new Promise(function (resolve, reject) {
console.log(1)
setTimeout(() = > resolve(p1), 1000)
})
p2.then(result= > console.log(result,2))
.catch(error= > console.log(error,4))
//3 // The promise is created and executed
//1 // Promise is created and executed
// Error: fail 4 // Do not execute 2 execute 4 because the state of P2 (which callback to execute) is determined by P1
Copy the code
P2 resolve A P1. The status of P2 is determined by the status of P1
The state of p1 is passed to P2, that is, the state of P1 determines the state of P2. If P1’s state is pending, p2’s callback waits for p1’s state to change. If P1 is in resolved or Rejected, the P2 callback will be executed immediately.
P2 resolve a P1p2
Own state is invalid, byp1
Determines the state ofp2
State, behindthen
Statements become specific to the latter (p1
)
P1 is a Promise. After 3 seconds, it changes to Rejected. The state of p2 changes after 1 second, and the resolve method returns P1. P2’s state is invalid because p2 returns a different Promise. P1’s state determines P2’s state. Therefore, subsequent then statements become for the latter (P1). After another 2 seconds, P1 changes to Rejected, triggering the callback specified by the catch method.
Calling resolve or Reject does not terminate the execution of the Promise’s argument function
In general, a call to resolve or reject completes a Promise, and subsequent actions should be placed in the then method rather than directly after resolve or reject. Therefore, it is best to precede them with a return statement so there are no surprises.
// It can be executed but has no effect
new Promise((resolve, reject) = > {
resolve(1);
console.log(2);
}).then(r= > {
console.log(r);
});
/ / 2
/ / 1
// It is normally recommended
new Promise((resolve, reject) = > {
return resolve(1);
// The following statement will not be executed
console.log(2);
})
Copy the code
Three states of promise
- Pending
- This is a big pity.
- Rejected (failed)
1. The promise object is initialized to pending
2. When you call resolve(success), there will be pending => depressing
3. Reject => Rejected when you call reject
Pending => depressing/Rejected, once modified, cannot be changed again
Promise object methods
Promise. Prototype. Then (resolved, rejected) method
Add a callback to the Promise instance when the state changes (resolve(success)/ Reject (failure))
The first parameter is thetaresolved
State callback function
The second parameter (optional
) isrejected
State callback function
The return value:then
Method returns a new onePromise
Instance (note, not the original onePromise
Instance)
// Ondepressing is a big song that is used to accept the promise's success
// onRejected is used to accept the reason the promise fails
promise.then(onFulfilled, onRejected);
Copy the code
Resolve (successfully) ondepressing will be called
const promise = new Promise((resolve, reject) = > {
resolve('fulfilled'); // State by pending => depressing
});
promise.then(result= > { // onFulfilled
console.log(result); // 'fulfilled'
}, reason= > { // onRejected will not be called
})
Copy the code
Reject onRejected is called
const promise = new Promise((resolve, reject) = > {
reject('rejected'); // The status is changed from Pending => Rejected
});
promise.then(result= > { // Ondepressing will not be called
}, reason= > { // onRejected
console.log(reason); // 'rejected'
})
Copy the code
Promise.prototype.catch(), which specifies the callback function when an error occurs
In chained writing, you can catch exceptions sent in the previous THEN
catch
methodsreturn
Is still aPromise object
, so it can be called laterthen
methods
If there is no error in catch, it is the Promise object of Resolve
Promise. catch(onRejected) is an alias of promise.then(null, onRejected) or promise.then(undefined, rejection)
An error that can be caught:
– 1. Reject Throws an error
– 2, then method specified by the callback function, the execution of the error (code syntax error)
Note: The second argument to the then function, onRejected, cannot catch the exception in the current ondepressing.
As a general rule, do not define a callback to the Reject state (the second argument to then) in the THEN method. Instead, use the catch method.
A Promise object must be followed by a catch method to handle errors that occur within a Promise.
promise.then(onFulfilled, onRrejected);
// Can be written as
promise.then(function(posts) {
// ...
}).catch(function(error) {
// Handle getJSON and errors that occurred while the previous callback function was running
console.log('Error! ', error);
});
Copy the code
Errors in the Promise object are “bubbling” in nature (always the next onecatch
Statement capture)
Errors in the Promise object are “bubbling” and are passed backwards until they are caught. That is, an error is always caught by the next catch statement.
getJSON('/post/1.json').then(function(post) {
return getJSON(post.commentURL);
}).then(function(comments) {
// some code
}).catch(function(error) {
// Handle errors from the first three promises
});
Copy the code
There are three Promise objects: one from getJSON and two from THEN. Any error thrown by either of them will be caught by the last catch.
Errors within a Promise do not affect code outside the Promise
const someAsyncThing = function() {
return new Promise(function(resolve, reject) {
// The next line is an error because x is not declared
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
Promise object, internal syntax error. When the browser runs this line, it will print ReferenceError: x is not defined, but it will not exit the process or terminate the script execution. After 2 seconds, it will still print 123.
The chain call after promise.catch
const someAsyncThing = function() {
return new Promise(function(resolve, reject) {
// The next line is an error because x is not declared
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
Copy the code
If no error is reported, the catch method is skipped and the subsequent THEN method is executed directly
Promise.resolve()
.catch(function(error) {
console.log('oh no', error);
})
.then(function() {
console.log('carry on');
});
// carry on
Copy the code
The catch method throws an error that will be caught by the next catch. No subsequent catch errors will be caught and passed to the outer layer
someAsyncThing().then(function() {
return someOtherAsyncThing();
}).catch(function(error) {
console.log('oh no', error);
// The next line is an error because y is not declared
y + 2;
}).catch(function(error) {
console.log('carry on', error);
});
// oh no [ReferenceError: x is not defined]
// carry on [ReferenceError: y is not defined]
Copy the code
Promise. Prototype. Finally (), is used to specify whetherPromise
What is the final state of the object
Used to specify actions that will be performed regardless of the final state of the Promise object. This method was introduced as a standard in ES2018.
Regardless of the final state of the promise, the callback specified by the finally method is executed after the callback specified by then or catch is executed.
The callback function of the finally method accepts no parameters, which means there is no way to know whether the Promise state is fulfilled or rejected. This suggests that operations in the finally method should be state independent and not depend on the result of a Promise’s execution.
promise
.then(result= >{...}). The catch (error= >{...}). Finally,() = > {···});
Copy the code
The server uses Promise to handle the request, and then uses the finally method to shut down the server.
server.listen(port)
.then(function () {
// ...
})
.finally(server.stop);
Copy the code
Promise chain call
promise.then
Method returns one per callNew Promise instance
So we can do the chain notation
function taskA() {
console.log("Task A");
}
function taskB() {
console.log("Task B");
}
function onRejected(error) {
console.log("Catch Error: A or B", error);
}
var promise = Promise.resolve();
promise
.then(taskA)
.then(taskB)
.catch(onRejected) Catch the exception in the previous then method
Copy the code
1. Chain calls pass results (arguments) in turn
After the previous callback completes, the result is passed as an argument to the next callback.
const p = new Promise(function (resolve, reject) {
setTimeout(() = > resolve('aa'), 1000)
})
p.then((e) = > {
console.log(e) //aa
return e;
}).then((e2) = > {
console.log(e) //aa
// if the preceding then does not return e, e2 is undefined
})
Copy the code
2. The previous callback returns a Promise object (with asynchronous operations)
The latter callback will wait for thePromise
The object is called only when its state changes
getJSON("/post/1.json").then(function(post) {
return getJSON(post.commentURL);
}).then(function funcA(comments) {
console.log("resolved: ", comments);
}, function funcB(err){
console.log("rejected: ", err);
});
Copy the code
3. Use the arrow function
getJSON("/post/1.json").then(
post= > getJSON(post.commentURL)
).then(
comments= > console.log("resolved: ", comments),
err= > console.log("rejected: ", err)
);
Copy the code
A static method for Promise
Promise. Resolve converts an existing object into a Promise object
Return a fulfilled Promise object
Promise.resolve('hello').then(function(value){
console.log(value);
});
//hello
Promise.resolve('hello');
/ / equivalent to
new Promise(resolve= > {
resolve('hello');
});
Copy the code
The parameters of the promise.resolve method are divided into four cases
(1) The parameter is an instance of Promise, thenPromise.resolve
willDo not make any changes
, returns the instance intact
If the argument is a Promise instance, promise.resolve will return the instance unchanged.
(2) The argument is a Thenable objectthen
Method object),Promise.resolve
Method will convert this object toPromise
Object, and execute immediatelythenable
The object’sthen
methods
Thenable objects refer to objects that have then methods, such as this one.
let thenable = {
then: function(resolve, reject) {
resolve(42); }};Copy the code
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) The argument is not an object with the then method, or is not an object at all, and returns a new onePromise
Object in the state ofresolved
If the parameter is a raw value, or an object that does not have a then method, the promise.resolve method returns a new Promise object with the state Resolved.
const p = Promise.resolve('Hello');
p.then(function (s){
console.log(s) // Hello
}).catch(function (s){
console.log(s) // P 'resolved' will not be executed
});
Copy the code
(4) Return an Resolved Promise object with no parameters
Return an Resolved Promise object directly.
const p = Promise.resolve();
p.then(function () {
// ...
});
Copy the code
immediatelyresolve()
thePromise
Object, is inThis "event cycle"
(Event loop), whileNot the next round
At the beginning of the cycle of events
setTimeout(function () {
console.log('three');
}, 0);
Promise.resolve().then(function () {
console.log('two');
});
console.log('one');
// one
// two
// three
Copy the code
In the code above:
SetTimeout (fn, 0) is executed at the start of the next “event loop”
Promise.resolve() is executed at the end of this “event loop.
Console.log (‘one’) is executed immediately and therefore printed first.
Promise.reject returns a Promise object in the Rejected state
const p = Promise.reject('Wrong');
/ / is equivalent to
const p = new Promise((resolve, reject) = > reject('Wrong'))
p.then(null.function (s) {
console.log(s)
});
/ / make a mistake
Copy the code
The arguments of the promise.reject () method are left as reject arguments and become arguments for subsequent methods. This is inconsistent with the promise.resolve method.
const thenable = {
then(resolve, reject) {
reject('Wrong'); }};Promise.reject(thenable)
.catch(e= > {
console.log(e === thenable)
})
// true
Copy the code
Promise.all accepts an array of Promise objects as arguments
Use to wrap multiple Promise instances into a new Promise instance
The promise. all method takes an array as an argument, and P1, P2, and p3 are all Promise instances
If not, the Promise. Resolve method (which returns a Promise object with a depressing state) will be called first, and the parameters will be converted to the Promise instance, which will then be processed further.
The promise. all method can take arguments that are not arrays, but must have an Iterator interface and each member returned is a Promise instance.
The state of P is determined by P1, P2 and P3, which can be divided into two situations:
(1) OnlyThe state of P1, P2 and P3 will become a pity
The state of P will become a pityP1, P2, P3
The return value of p is an array passed to p’s callback function
(2) as long asP1, P2, P3
One of them wasrejected
.p
The state of theta becomes thetarejected
At this time,The first one is rejected
Is passed top
The callback function of
const p1 = new Promise((resolve, reject) = > {
resolve(1);
});
const p2 = new Promise((resolve, reject) = > {
resolve(2);
});
const p3 = new Promise((resolve, reject) = > {
reject(3);
});
Promise.all([p1, p2, p3]).then(function(data){
console.log(data); // [1, 2, 3] The result order is the same as the order of the promise instance array
}).catch(function(err) {
console.log(err);
});
Copy the code
P1 will be resolved, P2 will be rejected,
But P2 has its own catch method, which returns a new Promise instance that P2 actually points to.
This instance will also become Resolved after executing the catch method, causing both instances in promise.all () to call the then callback and not the catch callback.
If P2 does not have its own catch method, the catch method of promise.all () is called, as shown in the code above
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)) // ["hello", Error: Error]
.catch(e= > console.log(e));
Copy the code
Promise.race takes an array of Promise objects as arguments, and as long as one call completes, subsequent calls are not executed, calling Promise.race directly
function timerPromisefy(delay) {
return new Promise(function (resolve, reject) {
setTimeout(function () {
resolve(delay);
}, delay);
});
}
var startDate = Date.now();
Promise.race([
timerPromisefy(10),
timerPromisefy(20),
timerPromisefy(30)
]).then(function (values) {
console.log(values); / / 10
});
Copy the code
Promise.allsettled () accepts a set of Promise instances as parameters and will not end until all of these parameter instances return a result
Method takes a set of Promise instances as parameters and wraps them into a new Promise instance. The wrapper instance will not complete until all of these parameter instances return the result, whether this is fulfilled or Rejected. This method was introduced by ES2020.
This method returns a new Promise instance. Once it is fulfilled, the state is always fulfilled and will not become Rejected. After the state becomes depressing, the Promise listener receives an array of parameters, each member corresponding to an incoming promise.allSettled () Promise instance.
Each object has a status attribute, whose value can only be the string fulfilled or the string Rejected.
Someday, the object has value attribute,
The Rejected attribute has reason, which corresponds to the return values of the two states.
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
Promise.any()
: As long as there is onefulfilled
State, the wrapper instance will becomefulfilled
State, allrejected
The wrapper instance becomesrejected
State, withPromise.race()
Very much like
The method takes a set of Promise instances as parameters and returns them wrapped as 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
Promise.any() is like the promise.race () method except that it does not end when a Promise changes to the Rejected state.
const promises = [
fetch('/endpoint-a').then(() = > 'a'),
fetch('/endpoint-b').then(() = > 'b'),
fetch('/endpoint-c').then(() = > 'c')];try {
const first = await Promise.any(promises);
console.log(first);
} catch (error) {
console.log(error);
}
Copy the code
In the code above, the parameter array for the promise.any () method contains three Promise operations. This is a big pity. As long as one of them becomes a big pity, the Promise. Any () will return a Promise. If all three operations become Rejected, the await command throws an error.
If you don’t use try… The catch structure and await command can be written as follows:
Promise.any(promises).then(
(first) = > {
// Any of the promises was fulfilled.
},
(error) = > {
// All of the promises were rejected.});Copy the code
example
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.try(), which uses the then method to specify the next step in the flow, regardless of whether f contains asynchronous operations
In real development, you often encounter a situation where:
I don’t know, or don’t want to distinguish, whether f is a synchronous function or an asynchronous operation, but both want to use Promise to handle it.
Promise.try simulates a try block, just as promise.catch simulates a catch block.
This allows the then method to specify the next step in the flow, regardless of whether f contains an asynchronous operation, and the catch method to handle any errors thrown by F.
This is the way you would normally write it.
Promise.resolve().then(f)
Copy the code
One disadvantage of this notation is that if f is a synchronous function, it will be executed at the end of the current event loop.
const f = () = > console.log('now');
Promise.resolve().then(f);
console.log('next');
// next
// now
Copy the code
Let synchronous functions execute synchronously, asynchronous functions execute asynchronously, and let them have a uniform API
1. Async functions
const f = () = > console.log('now');
(async () => f())();
console.log('next');
// now
// next
Copy the code
In the above code, the second line is an immediate anonymous function that executes the async function immediately, so if f is synchronous, the result is synchronized;
If f is asynchronous, then can be used to specify the next step, as follows.
(async () => f())()
.then(...)
.catch(...) //async () => f() eats an error thrown by f() and catches it with promise.catch
Copy the code
2, the new Promise ()
const f = () = > console.log('now');
(
() = > new Promise(
resolve= > resolve(f())
)
)();
console.log('next');
// now
// next
Copy the code
usePromise.try
methodsalternative
The aboveSelf-executing function writing
, Promise. Try (f)
const f = () = > console.log('now');
Promise.try(f);
console.log('next');
// now
// next
Copy the code
If you want to manage your processes using then methods, it is best to wrap them all in promise.try to better manage exceptions
Promise.try(() = > database.users.get({id: userId}))
.then(...)
.catch(...)
Copy the code