Peomise principle

Share from my colleague Zhao Jie

const MyPromise = (() => { const PENDING = "pending", RESOLVED = "resolved", REJECTED = "rejected", PromiveValue = Symbol("PromiseStatus"), thenables = Symbol("thenables"), //thenable catchables = Symbol("catchbles"), SettleHandle = Symbol("settleHandle"), settleHandle = Symbol("settleHandle"), LinkPromise = Symbol("linkPromise"); Return class MyPromise {/** * change the state of the current Promise * @param {*} newStatus * @param {*} newValue * @param {*} Queue Queue of jobs executed */ [changeStatus](newStatus, newValue, queue) {if (this[PromiseStatus]! == PENDING) {// State cannot change return; } this[PromiseStatus] = newStatus; this[PromiveValue] = newValue; Queue. ForEach (handler => handler(newValue)); } /** ** @param {*} constructor(executor) {this[PromiseStatus] = pending; this[PromiveValue] = undefined; this[thenables] = []; Resolved this[catchables] = []; Resolve => {this[changeStatus](RESOLVED, data, this[thenables]); } const reject = reason => { this[changeStatus](REJECTED, reason, this[catchables]); } try { executor(resolve, reject) } catch (err) { reject(err); ImmediatelyStatus Specifies the state that needs to be executed immediately * @PARam {*} queue Specifies the job queue */ [settleHandle](handler, immediatelyStatus, queue) { if (typeof handler ! == "function") { return; } immediatelyStatus === immediatelyStatus; // immediatelyStatus == immediatelyStatus; // immediatelyStatus == immediatelyStatus; // immediatelyStatus == immediatelyStatus; }, 0); } else { queue.push(handler); } } [linkPromise](thenalbe, catchable) { function exec(data, handler, resolve, reject) { try { const result = handler(data); If (result instanceof MyPromise) {result.then(d => {resolve(d)}, err => {reject(err); }) } else { resolve(result); } } catch (err) { reject(err); } } return new MyPromise((resolve, reject) => { this[settleHandle](data => { if(typeof thenalbe ! == 'function'){ resolve(data); return; } exec(data, thenalbe, resolve, reject); }, RESOLVED, this[thenables]) this[settleHandle](reason => { if(typeof catchable ! == 'function'){ reject(reason); return; } exec(reason, catchable, resolve, reject); }, REJECTED, this[catchables]) }) } then(thenable, catchable) { return this[linkPromise](thenable, catchable); } catch(catchable) { return this[linkPromise](undefined, catchable); } static all(proms) { return new MyPromise((resolve, reject) => { const results = proms.map(p => { const obj = { result: undefined, isResolved: false } p.then(data => { obj.result = data; obj.isResolved = true; Const unResolved = results.filter(r =>!) const unResolved = results.filter(r =>! Resolved) if (unResolved. Length === 0) {// resolve(results.map(r => r.result)); } }, reason => { reject(reason); }) return obj; }) }) } static race(proms) { return new MyPromise((resolve, reject) => { proms.forEach(p => { p.then(data => { resolve(data); }, err => { reject(err); }) }) }) } static resolve(data) { if (data instanceof MyPromise) { return data; } else { return new MyPromise(resolve => { resolve(data); }) } } static reject(reason) { return new MyPromise((resolve, reject) => { reject(reason); }}}}) ();Copy the code
Const isFunction = variable => typeof variable === 'function' const PENDING = 'PENDING' const FULFILLED = 'FULFILLED' const REJECTED = 'REJECTED' class MyPromise { constructor (handle) { if (! IsFunction (handle)) {throw new Error('MyPromise must accept a function as a parameter') This._value = undefined // Add successful callbacks this. _implemented queues = [] // Add failed callbacks this._rejectedQueues = [] // handle try {handle(this._resolve.bind(this), Bind (this))} catch (err) {this._reject(err)}} // Resolve (val) {const run = () => { if (this._status ! Const rundepressing = (value) => {let cb; While (cb = this._disabling queues. Shift ()) {cb(value)}} Const runRejected = (error) => {let cb; While (cb = this._rejectedqueues. Shift ()) {cb(error)}} /* If resolve is a Promise object, The state of the current Promsie will change only after the Promise object state changes. Then (value => {this._value = value this._status = depressing  runFulfilled(value) }, err => { this._value = err this._status = REJECTED runRejected(err) }) } else { this._value = val this._status = // In order to support synchronous promises, Async setTimeout(run, 0)} _reject (err) {if (this._status! Const run = () => {this._status = REJECTED this._value = err let cb; While (cb = this._rejectedqueues. Shift ()) {cb(err)}} SetTimeout (run, 0)} then (onFulfilled, onRejected) {const {_value, _status} = this // return new MyPromise((onledNext, OnRejectedNext) => {// This is a big pity => {try {if (! isFunction(onFulfilled)) { onFulfilledNext(value) } else { let res = onFulfilled(value); If (res instanceof MyPromise) {// If the current callback returns MyPromise, Res. then(ononledNext, onRejectedNext)} else {// Otherwise, the result will be passed directly as an argument to the next then callback function. Onlednext (res)}}} catch (err) {// If the function fails, OnRejectedNext (err)}} let Rejected = error => {try {if (! isFunction(onRejected)) { onRejectedNext(error) } else { let res = onRejected(error); If (res instanceof MyPromise) {// If the current callback returns MyPromise, Res. then(ononledNext, onRejectedNext)} else {// Otherwise, the result will be passed directly as an argument to the next then callback function. Onlednext (res)}}} catch (err) {// If the function fails, OnRejectedNext (err)}} Switch (_status) {// Add the then method callback to the execution queue for case Pending when the state is pending: This._rejectedqueues. Push (rejected) break // This._rejectedQueues. fulfilled(_value) break case REJECTED: Return this. Then (rejected(_value) break}})} // Add a catch (onRejected) {return this. Static resolve (value) {// If MyPromise = MyPromise; If (value instanceof MyPromise) return value return MyPromise(resolve => resolve(value)) Reject (value) {return new MyPromise((resolve,reject) => reject(value))} static all (list) { Return new MyPromise((resolve, reject) => {/** ** let values = [] let count = 0 for (let [I, P] of list.entries()) {// array parameters if not MyPromise instance, Resolve this. Resolve (p). Then (res => {values[I] = res count++ //) This will be a big pity. The MyPromise state will become a big pity if (count === list.length) resolve(values)}, Err => {// MyPromise is rejected reject(err)})}} static race (list) {return new MyPromise((resolve, reject) => {for (let p of list) { Resolve (p). Then (res => {resolve(res)}, err => { reject(err) }) } }) } finally (cb) { return this.then( value => MyPromise.resolve(cb()).then(() => value), reason => MyPromise.resolve(cb()).then(() => { throw reason }) ); }}Copy the code