JavaScript is a single-threaded language that achieves asynchronous operations by maintaining an execution stack and a task queue. setTimeout and Ajax are typical asynchronous operations, and Promise is a solution for asynchronous operations used to represent the eventual completion or failure and resulting value of an asynchronous operation. Promise has various open source implementations and was standardized in ES6, directly supported by browsers.
newPromise(function(resolve, reject){/* executor */// Execution code with specified positions for resolve and reject callbacks});
The executor is a function with two parameters, resolve and reject. When the Promise constructor is executed, the executor function is immediately called, and the resolve and reject functions are passed as parameters to the executor. When the resolve and reject functions are called, the promise status is changed to fulfilled or rejected, respectively. The executor typically performs some asynchronous operations internally. Once the asynchronous operation is completed, either the resolve function is called to change the promise status to fulfilled, or the reject function is called to change the promise status to rejected. If an error is thrown in the executor function, the promise status is rejected, and the return value of the executor function is ignored.
pending: Initial state, neither fulfilled nor rejected.
fulfilled: Indicates a successful operation completion.
rejected: Indicates a failed operation.
Promise objects can only transition from pending to fulfilled or from pending to rejected. Once in the fulfilled or rejected state, the status does not change.
Drawback: Cannot cancel a Promise; once created, it executes immediately and cannot be canceled mid-process. If not actively caught, exceptions thrown in a Promise are not reflected externally. In Firefox, exceptions are not thrown, while in Chrome, exceptions are thrown but do not trigger the winodw.onerror event. When in the pending state, the current progress cannot be determined (just started or about to complete).
Promise can be chained to avoid the callback hell caused by excessive asynchronous operations; by default, the then() function returns a new Promise different from the original one.
var promise =newPromise(function(resolve,reject){var rand = Math.random()*2;setTimeout(function(){if(rand <1)resolve(rand);elsereject(rand);},1000)})promise.then(function(rand){ console.log("resolve",rand);// resolve callback executed}).catch(function(rand){ console.log("reject",rand);// reject callback executed}).then(function(){ console.log("Then executed again");return Promise.resolve(1);}).then(function(num){ console.log(num,"can continue to execute and receive parameters");})
Performing multiple asynchronous operations, assuming only resolve will continue to the next asynchronous operation.
var promise =newPromise(function(resolve,reject){var rand = Math.random()*2;setTimeout(function(){if(rand <1)resolve(rand);elsereject(rand);},1000)})promise.then(function(rand){ console.log("resolve",rand);// resolve callback executedreturnnewPromise(function(resolve,reject){setTimeout(function(){resolve(10000);},1000)})}).then(function(num){ console.log(num);}).catch(function(rand){ console.log("reject",rand);// Catch the reject callback and exception})
Using catch to catch exceptions.
var promise =newPromise(function(resolve,reject){thrownewError("Error");// Throws an exception})promise.then(function(){ console.log("Normal execution");}).catch(function(err){ console.log("reject",err);// Catch the exception
then itself can accept two parameters resolve and reject
var promise =newPromise(function(resolve,reject){var rand = Math.random()*2;setTimeout(function(){if(rand <1)resolve(rand);elsereject(rand);},1000)})promise.then(function(rand){ console.log("resolve",rand);// Callback for resolve},function(rand){ console.log("reject",rand);// Callback for reject})
This method returns a new promise object. This promise object is triggered to be successful only when all the promise objects in the iterable parameter are successful. Once any promise object inside the iterable fails, it immediately triggers the failure of this promise object. After the new promise object is triggered to be successful, it will return an array containing the return values of all promise objects in iterable as the success callback return value, in the same order as in the iterable. If this new promise object is triggered to be in a failed state, it will use the error information of the first promise object inside iterable that triggers a failure as its own failure error message. The Promise.all method is often used to handle the status collection of multiple promise objects.
var p1 =newPromise((resolve, reject)=>{resolve("success1");})var p2 =newPromise((resolve, reject)=>{resolve("success2");})var p3 =newPromise((resolve, reject)=>{reject("fail");})Promise.all([p1, p2]).then((result)=>{ console.log(result);// Successful state //["success1", "success2"]}).catch((error)=>{ console.log(error);})Promise.all([p1,p3,p2]).then((result)=>{ console.log(result);}).catch((error)=>{ console.log(error);// Failed state // fail})
When any child promise in the iterable parameter is successful or fails, the parent promise is immediately called with the success return value or failure details of the child promise as parameters for the parent promise's corresponding handler, and returns the promise object.
var p1 =newPromise((resolve, reject)=>{setTimeout(()=>{resolve("success");},1000);})var p2 =newPromise((resolve, reject)=>{setTimeout(()=>{reject("failed");},2000);})Promise.race([p1, p2]).then((result)=>{ console.log(result);// If p1 gets the result first, then execute the p1 callback}).catch((error)=>{ console.log(error);})
### Promise.resolve(value)Returns a `Promise` object whose state is determined by the given `value`. If the value is a `thenable`(i.e., an object with a `then` method), the final state of the returned `Promise` object is determined by the execution of the `then` method.Otherwise(if the `value` is null, a primitive type, or an object without a `then` method), the state of the returned `Promise` object is `fulfilled`, and the `value` is passed to the corresponding `then` method. Usually,if you are unsure whether a value is a `Promise` object, use `Promise.resolve(value)` to return a `Promise` object, so that you can use the `value`in the form of a `Promise` object. Do not call `Promise.resolve` on a `thenable` that resolves to itself,asthis will result in infinite recursion,as it attempts to flatten infinitely nested `promise`.```javascript
// If the value is null or a primitive type, directly return a fulfilled Promise objectvar promise = Promise.resolve(1);promise.then((num)=>{ console.log(num);// 1}).catch((err)=>{ console.log(err);});// If the parameter is a Promise instance, Promise.resolve will not modify it and will return the instance as isvar p1 = Promise.resolve(1);var p2 = Promise.resolve(p1);console.log(p1 === p2);// truep2.then((value)=>{ console.log(value);// 1});// If the value is a thenable object, the final state of the returned Promise object is determined by the then method executionvar thenable ={then:(resolve, reject)=>resolve(1)};var p1 = Promise.resolve(thenable);p1.then((value)=>{ console.log(value);// 1}).catch((err)=>{ console.log(err);});
Adds resolve fulfillment and reject rejection callbacks to the current promise, and returns a new promise that will be resolved with the return value of the callback.
Adds a reject rejection callback to the current promise, and returns a new promise. When this callback function is invoked, the new promise will be resolved with its return value. Otherwise, if the current promise enters the fulfilled state, the completion result of the current promise will be the completion result of the new promise.
Adds an event handling callback to the current promise object, and after the original promise object is resolved, returns a new promise object. The callback will be invoked after the current promise has completed, regardless of whether the current promise is in the fulfilled or rejected state.