When multiple operations are required, multiple callback functions can be nested, resulting in unintuitive code known as callback hell, which is usually solved with promises
I’ll make a Promise to you after a certain amount of time. When is it used over a period of time? The answer is asynchronous operations, which are things that take a long time to produce results, such as network requests, reading local files, etc
Constructor initializes the logic
const PENDING = 'pending'; // this is a big pity'fulfilled'; // Const REJECTED ='rejected'; / / the initial stateletself = this; // Cache the current promise instance self.status = PENDING; // Set the state self.onresolvedCallbacks = []; Self.onrejectedcallbacks = []; // Define an array of failed callbacksCopy the code
An executor executor that takes resolve and reject. The new Promise executor will execute
Promise has three states: the initial state is “pending”, the success state is “depressing”, and the failure state is “Rejected”. If the code succeeds, it will not fail. If it is always pending, it will never give you a definite answer
If a promise is in a pending state, it can be converted to a successful state. If a promise is already in a successful or failed state, it does nothing
function resolve(value){
if(value! =null &&value.then&&typeof value.then =='function') {return value.then(resolve,reject);
}
setTimeout(function() {if(self.status == PENDING){ self.status = FULFILLED; self.value = value; self.onResolvedCallbacks.forEach(cb=>cb(self.value)); }})}functionReject (reason) {/ / 2.1.2setTimeout(function() {if(self.status == PENDING){ self.status = REJECTED; self.value = reason; self.onRejectedCallbacks.forEach(cb=>cb(self.value)); }}); }}Copy the code
Because this function can execute in an exception, you need to catch it. If something goes wrong, reject the error object. If it fails, reject the promise, the cause of the failure, and try… catch(e)… For processing
try{
executor(resolve,reject);
}catch(e){
reject(e);
};
Copy the code
The resolution process for promises
function resolvePromise(promise2,x,resolve,reject){
if(promise2 === x){
return reject(new TypeError('Circular reference'));
}
let called = false;
if(x instanceof Promise){
if(x.status == PENDING){
x.then(function(y){
resolvePromise(promise2,y,resolve,reject);
},reject);
}else{ x.then(resolve,reject); }}else if(x! = null &&((typeof x=='object')||(typeof x == 'function'))){
try{
let then = x.then;
if(typeof then= ='function'){
then.call(x,function(y){
if(called)return;
called = true;
resolvePromise(promise2,y,resolve,reject)
},function(err){
if(called)return;
called = true;
reject(err);
});
}else{
resolve(x);
}
}catch(e){
if(called)return;
called = true; reject(e); }}else{ resolve(x); }}Copy the code
The then method is used to specify the actions to be performed when the state of the Promise object changes. The first function (ondepressing) is performed in the resolve method, and the second function (onRejected) is performed in the reject method. In this method, if the successful and failed callbacks are not passed, Then means that the then has no logic and only throws the value backwards
Promise.prototype.then = function(onFulfilled,onRejected){
onFulfilled = typeof onFulfilled == 'function'? onFulfilled:function(value){return value};
onRejected = typeof onRejected == 'function'? onRejected:reason=>{throw reason};let self = this;
let promise2;
if(self.status == FULFILLED){
return promise2 = new Promise(function(resolve,reject){
setTimeout(function(){
try{
letx =onFulfilled(self.value); resolvePromise(promise2,x,resolve,reject); }catch(e){ reject(e); }})}); }if(self.status == REJECTED){
return promise2 = new Promise(function(resolve,reject){
setTimeout(function(){
try{
letx =onRejected(self.value); resolvePromise(promise2,x,resolve,reject); }catch(e){ reject(e); }})}); }if(self.status == PENDING){
return promise2 = new Promise(function(resolve,reject){
self.onResolvedCallbacks.push(function(){
try{
letx =onFulfilled(self.value); resolvePromise(promise2,x,resolve,reject); }catch(e){ reject(e); }}); self.onRejectedCallbacks.push(function(){
try{
letx =onRejected(self.value); resolvePromise(promise2,x,resolve,reject); }catch(e){ reject(e); }}); }); }}Copy the code
The chain call to promise
- Each call returns a new Promise instance
- Arguments to chained calls are passed by return value: that is, the first then succeeds and its return value is taken as an argument to the next successful callback
then
The reason you can write a chained call is that it always returns one every time the method is executedPromise
object
Then (undefined, onRejected); This is just an alias for the method. That is, this method is used to register the callback function catch when the State of the Promise object changes to Rejected
Promise.prototype.catch = function(onRejected){
this.then(null,onRejected);
}
Copy the code
Promise.all takes an array of Promise objects as arguments, and calls the.then method when all the Promise objects in the array are resolved or reject
Promise.all = function(promises){
return new Promise(function(resolve,reject){
let done = gen(promises.length,resolve);
for(leti=0; i<promises.length; i++){ promises[i].then(function(data){
done(i,data); },reject); }}); }Copy the code
As long as one of the Promise objects enters the FulFilled or Rejected state, the following processing will be continued
Promise.race = function(promises){
return new Promise(function(resolve,reject){
for(leti=0; i<promises.length; i++){ promises[i].then(resolve,reject); }}); }Copy the code
If you’re given a method that requires you to pass in a promise, but you only have a generic value, you can use this method to turn that generic value (string Number object) into a Promise object that returns an immediate promise
Promise.resolve = function(value){
return new Promise(function(resolve){
resolve(value);
});
}
Copy the code
Return a promise that fails immediately
Promise.reject = function(reason){
return new Promise(function(resolve,reject){
reject(reason);
});
}
Copy the code