Written in the beginning
- I see some technology groups are developing these days
Promise
Related to some of the implementation, oneself recently also look atES6
Some of the content, so I plan to sort out their own, improve the understanding; - This article is suitable for those who know and use it
Promise
If you don’t know or use itPromise
I suggest you take a look at it firstECMAScript6 Promise of getting started.
What is thePromise
- A solution to asynchronous programming;
Promise
Is a container that holds the result of some event (usually an asynchronous operation) that will end in the future.
The characteristics of
- The status of an object is not affected.
Promise
The object represents an asynchronous operation with three states:pending
(In progress),fulfilled
(Successfully) andrejected
(Failed). - Once the state changes, it never changes again, and you can get this result at any time.
Promise
The state of an object can change in only two ways: frompending
intofulfilled
And from thepending
intorejected
.
Simple implementation
Process analysis
- Image credit: MDN
Initialize onePromise
- The original
Promise
// The Promise constructor receives an executor function, and after the executor function has performed a synchronous or asynchronous operation, Resolve and reject const promise = new promise (function(resolve, reject) {/* Call resolve and pass value if the operation fails. Call reject and pass reason */})Copy the code
- Contains the current state
- The current value
fulfilled
Is an array of callback functionsrejected
Is an array of callback functions
const PENDING = 'pending'; const FULFILLED = 'fulfilled'; const REJECTED = 'rejected'; const NewPromise = function(executor) { const _this = this; _this.status = PENDING; // state _this.data = undefined; // value _this.onresolvedCallback = []; // this. OnRejectedCallback = []; Function resolve(value) {// Resolve (value) {... } function reject(reason) {... } try { executor(resolve, reject); } catch (error) { reject(error); }}Copy the code
perfectresole
andreject
resole
Is a successful call and needs to be changed to statelessfulfilled
, then the current value is set to the value passed in, and the execution is traversedonResolvedCallback
The callback in.
This is a pity/rejected setTimeout(function()) {// this is a pity/rejected setTimeout(function()) {// This is a pity/rejected setTimeout(function()) {// This is a pity/rejected setTimeout(function()) {// This is a pity/rejected setTimeout(function()) (_this.status === PENDING) { _this.status = FULFILLED; _this.data = value; _this.onResolvedCallback.forEach(callback => callback(value)); }}); }Copy the code
reject
The implementation andresolve
Similar, except that the state is changed torejected
And carry outonRejectedCallback
.
Function reject(reason) {setTimeout(function() {// Execute all callback functions asynchronously if (_this.status === PENDING) {_this.status = REJECTED; _this.data = reason; _this.onRejectedCallback.forEach(callback => callback(reason)); }}); }Copy the code
- Now you have the basics
Promise
, you can like usePromise
Use it as well, but no other methods have been added.
// 测试
const promise = new NewPromise(function(resolve, reject) {
console.log('ss', 11)
})
Copy the code
then
methods
Promise
Object has onethen
Method used to register in thisPromise
Callback after state determination,then
Methods need to be written on the prototype chain (why are they written on the prototypeJavaScript
Basic). inPromise/A
standardIn, clearly stipulatedthen
To return a new object, we return a new object in our implementation.
/ / then mount to NewPromise on prototype. The prototype. Then = function (onResolved onRejected) {const _this = this; if ( typeof onResolved ! == 'function') { onResolved = function(value) { return value } } if ( typeof onRejected ! // Const common = function(data, resolve, resolve); // Const common = function(data, resolve, resolve); This is a big pity. // This is a big pity. This is a big pity. onResolved(data) : onRejected(data) if( value instanceof Promise) { value.then(resolve, Reject)} resolve(value)} catch (error) {reject(error)}} const pendingCommon = function (data, flag, This is a big pity. // This is a big pity. // This is a big pity. onResolved(data) : onRejected(data) if( value instanceof Promise) { value.then(resolve, reject) } resolve(value) } catch (error) { reject(error) } } if (_this.status === PENDING) { return new NewPromise(function(resolve, reject) { _this.onResolvedCallback.push((value) => { pendingCommon(value, FULFILLED, resolve, reject); }) _this.onRejectedCallback.push((reason) => { pendingCommon(reason, REJECTED, resolve, reject); }) }) } else { // resolve / reject return new NewPromise(function (resolve, reject) { setTimeout(function () { common(_this.data, resolve, reject) }) }) } }Copy the code
rightresolve
Methods improved again
- judge
rosolve
Is the value ofPromise
If it isPromise
Continue to perform.then
Methods.
Function resolve(value) {then + if (value instanceof Promise) {return (value instanceof Promise) value.then(resolve, reject) + } ... }Copy the code
catch
methods
- capture
Promise
Exception error.
/ / catch method NewPromise. Prototype. Catch = function (onRejected) {return this. Then (null, onRejected)}Copy the code
finally
methods
finally()
Method is used to specify whetherPromise
The operation to be performed in the final state of the object.
// finally
NewPromise.prototype.finally = function (fun) {
return this.then((value) => {
return NewPromise.resolve(fun()).then(() => value);
}, (err) => {
return NewPromise.resolve(fun()).then(() => {
throw err;
});
});
};
Copy the code
resolve
methods
- Existing object converted
Promise
Object, instance of which is in the state offulfilled
.
NewPromise.resolve = function(value) { if (value instanceof Promise) return value; if (value === null) return null; / / to judge if it is a promise if (typeof value = = = 'object' | | typeof value = = = 'function') {try {/ / judgment method are then let then = value.then; if (typeof then === 'function') { return new NewPromise(then.call(value)); Catch (e) {return new NewPromise((resolve, reject) =>{reject(e); }); } } return new NewPromise( (resolve, reject) =>{ resolve(value); }); }Copy the code
reject
methods
- Existing object converted
Promise
Object, instance of which is in the state ofrejected
. The implementation andresolve
The method is similar, and finally return is changedreject
.
NewPromise.reject = function(reason) {
...
return new NewPromise( (resolve, reject) =>{
reject(reason);
});
}
Copy the code
all
methods
Promise.all
Method is used to wrap multiple Promise instances into a new onePromise
Instance; The arguments to a method may not be arrays, but they must beIterator
Interface, and each member returned isPromise
Instance.
// all NewPromise.all = function(promises) { return new NewPromise((resolve, Reject) => {const result = [] // Promise = array.isarray (promises)? promises : [] const len = promises.length; if(len === 0) resolve([]); let count = 0 for (let i = 0; i < len; ++i) { if(promises[i] instanceof Promise) { promises[i].then(value => { count ++ result[i] = value if (count === len) resolve(result) }, reject) } else { count ++ result[i] = promises[i] if (count === len) resolve(result) } } }) }Copy the code
race
methods
Promise.race()
The method is also multiplePromise
Instance, wrapped into a new onePromise
Instance.- As long as one instance of the parameters changes state first,
Promise.race()
The state of the changes. The one who changed firstPromise
The return value of the instance is passed toPromise.race()
The callback function of.
// race
NewPromise.race = function (promises) {
return new NewPromise((resolve, reject) => {
promises = Array.isArray(promises) ? promises : []
promises.forEach(promise => {
promise.then(resolve, reject)
})
})
}
Copy the code
deferred
methods
- Returns an object with a Promise method.
// defered
NewPromise.deferred = function() {
const dfd = {}
dfd.promise = new NewPromise(function(resolve, reject) {
dfd.resolve = resolve
dfd.reject = reject
})
return dfd
}
Copy the code
allSettled
methods
Promise.allSettled()
Method accepts a set ofPromise
The instance is wrapped as a new parameterPromise
This will be fulfilled only after all these parameter instances return the result, whether fulfilled or Rejected. Returns an array containing all the results.
NewPromise.allSettled = function (promises) { return new NewPromise((resolve, reject) => { promises = Array.isArray(promises) ? promises : [] let len = promises.length; const argslen = len; if (len === 0) return resolve([]); let args = Array.prototype.slice.call(promises); Function resolvePromise(index, value) {if(typeof value === 'object') {const then = value.then; if(typeof then === 'function'){ then.call(value, function(val) { args[index] = { status: 'fulfilled', value: val}; if(--len === 0) { resolve(args); } }, function(e) { args[index] = { status: 'rejected', reason: e }; if(--len === 0) { reject(args); } }) } } } for(let i = 0; i < argslen; i++){ resolvePromise(i, args[i]); }})}Copy the code
test
Based on the test
// test const promise = new NewPromise(function(resolve, reject) {console.log('ss', 11); resolve(123); })Copy the code
then
test
promise.then(val => {
console.log('val', val)
})
Copy the code
catch
test
const promise = new NewPromise(function(resolve, reject) {
console.log('ss', 11);
reject('errr')
})
promise.catch(err => {
console.log('err', err)
})
Copy the code
finally
test
const resolved = NewPromise.resolve(1);
const rejected = NewPromise.reject(-1);
const resolved1 = NewPromise.resolve(17);
const p = NewPromise.all([resolved, resolved1, rejected]);
p.then((result) => {
console.log('result', result)
}).catch(err => {
console.log('err', err)
}).finally(() => {
console.log('finally')
})
Copy the code
resolve
test
const resolved = NewPromise.resolve(1);
resolved.then(val => {
console.log('resolved', val)
})
Copy the code
reject
test
const rejected = NewPromise.reject(-1);
rejected.catch(val => {
console.log('rejected', val)
})
Copy the code
all
test
const resolved = NewPromise.resolve(1);
const rejected = NewPromise.reject(-1);
const resolved1 = NewPromise.resolve(17);
const p = NewPromise.all([resolved, resolved1, rejected]);
p.then((result) => {
console.log('result', result)
}).catch(err => {
console.log('err', err)
})
Copy the code
allSettled
test
const resolved = NewPromise.resolve(1);
const rejected = NewPromise.reject(-1);
const resolved1 = NewPromise.resolve(17);
const p = NewPromise.allSettled([resolved, resolved1, rejected]);
p.then((result) => {
console.log('result', result)
})
Copy the code
All the code
- Please click to jump
GitHub
Warehouse:Handwritten Promise implementation, wiggle your finger and give the project oneStar
Thank you!
reference
ECMAScript 6 introduction to 22 high-frequency JavaScript handwritten interview questions and answers
- Have to help you leave your praise 👍 bai, your support is the power of my output.
supplement
rightPromise.all
There is doubt
- Tested native
Promise.all
Methods.
- When all the pity
Change the asynchronous success return sequence of the all method
- The code for the all method above has been updated.
- Test cases, thanks to AshoneA for asking the question.
const promise1 = new Promise(resolve => {
setTimeout(() => {
resolve("promise1");
}, 200);
});
const promise2 = new Promise(resolve => {
setTimeout(() => {
resolve("promise2");
}, 100);
});
NewPromise.all([promise1, promise2]).then(value => {
console.log(value);
});
Promise.all([promise1, promise2]).then(value => {
console.log(value);
});
Copy the code
- Previous test results. [Test Address](
Codesandbox. IO/s/musing – cu…)
- Modified test results.