Make writing a habit together! This is my first day to participate in the “Gold Digging Day New Plan · April More text challenge”, click to see the details of the activity.

I hope I can force myself to make it through

preface

Keep writing and learning to write promises by hand

  • 1. Define a basic Promise method and then results
  • 2. Asynchronous execution problems
  • 3. Then method chain call
  • 4. Then returns Promise processing and then pass through
  • 5. Then code redundancy optimization and error handling catch
  • 6. Promise. Resolve and Promise. Reject
  • 7.Promise.all
  • 8.Promise.race

In practice, you can synchronize and compare with native promises to better understand Promise implementation

1. Define a basic Promise method and then get results

(function () {
  function Typromise(executor) { // executor new Promise method passed in
    this.state = 'pending' // There is a promise state, which is fulfilled Rejected Pending
    this.result = ' ' // New Promise execution result
    // The executor passes two methods to define a new Promise: resolve,reject
    let resolve = (value) = > {
      if (this.state === 'pending') { // The state changes before pending and before resolve
        this.state = 'fulfilled'
        this.result = value
      }
    }
    let reject = (reason) = > {
      if (this.state === 'pending') { Pending (reject); reject (reject
        this.state = 'rejected'
        this.result = reason; }}this.then = (onFulfilled, onRejected) = > { // then accepts two methods, resolve or reject
      if (this.state === 'fulfilled') { // If the state is fufilled, perform the ondepressing method passed in
        onFulfilled(this.result)
      }
      if (this.state === 'rejected') { // reject, reject, execute the passed onRejected method
        onRejected(this.result)
      }
    }
    // If a new Promise fails, try catch is required
    try {
      executor(resolve, reject) // Execute resolve or reject when new Promise is implemented
    } catch (error) {
      reject(error) // new Promise returns an error}}window.Typromise = Typromise
})()
Copy the code

Contrast test

console.log('1. -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- - written promise');
let ty = new Typromise((resolve, reject) = > {
    resolve('fulfilled - written');
    // reject('reject- write ');
    console.log('2.new Typromise')
}).then(value= > { 
    console.log('4.value: ', value);
}, error= > { 
    console.log('4.error: ', error);
})
console.log('3.-----------------ty')

console.log('1. -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- the original Promise');
let p = new Promise((resolve, reject) = > {
    resolve('fulfilled - official');
    // reject('reject- official ');
    console.log('2.new Promise')
}).then(value= > { 
    console.log('4.value: ', value);
}, error= > { 
    console.log('4.error: ', error);
})
console.log('3.-----------------p')
Copy the code

conclusion: The above test indicates that the output of the 4th should be later than that of the 3rd, so it can be assumed thatthenThe methods inside should be asynchronous

2. Asynchronous execution problems

1. Methods in then execute asynchronously

Modify the then method to execute asynchronously

function Typromise(executor){...this.then = (onFulfilled, onRejected) = > { // then accepts two methods, resolve or reject
      if (this.state === 'fulfilled') { // If the state is fufilled, perform the ondepressing method passed in
        setTimeout(() = > {
          onFulfilled(this.result)
        });
      }
      if (this.state === 'rejected') { // reject, reject, execute the passed onRejected method
        setTimeout(() = > {
          onRejected(this.result) }); ...}}}Copy the code

2. Asynchronous execution issues in new Promises

Testing: New Promise exists when resolve or Reject is executed asynchronously

console.log('1. -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- - written promise');
let ty = new Typromise((resolve, reject) = > {
    setTimeout(() = > {
        // this will be a big pity.
        reject('reject - written');
        console.log('2.new Typromise')},1000);
}).then(value= > {
    console.log('4.value: ', value);
}, error= > {
    console.log('4.error: ', error);
})
console.log('3.-----------------ty')

console.log('1. -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- the original Promise');
let p = new Promise((resolve, reject) = > {
    setTimeout(() = > {
        // resolve('fulfilled-官方');
        reject('reject - official');
        console.log('2.new Promise')},1000);
}).then(value= > { 
    console.log('4.value: ', value);
}, error= > { 
    console.log('4.error: ', error);
})
console.log('3.-----------------p')
Copy the code

conclusion: The above test instructions are innew PromiseUse insidesetTimeoutNot executed after asynchronous executionthenMethod returns the value, and thus the result4. Value: depressing – handwritingIt doesn’t show up in the log

Modify the logic in the then method when a new Promise is executed asynchronously into a pending state

  • 1. Define a variable to store the lazy execution methodcallback = { }
  • 2. Due to thenew PromiseIn theresolvewithrejectinsetTimeoutExecute asynchronously in. sothenWill execute first, at this pointstateispending.thenExecute the firstthenIt came throughonFulfilledwithonRejecteddepositcallbackWaiting for asynchronousresolvewithrejectcall
  • In 3.resolveorrejectWhen called, executeonFulfilledoronRejectedmethods

The subscript ⭐️⭐️ is used for the modification

(function () {
  function Typromise(executor) { // executor new Promise method passed in
    this.state = 'pending' // There is a promise state, which is fulfilled Rejected Pending
    this.result = ' ' // New Promise execution result
    this.callback = {} // Define an object for the collection method call ⭐️⭐️ Modify the link link link. Define the callback variable store
    // The executor passes two methods to define a new Promise: resolve,reject
    let resolve = (value) = > {
      if (this.state === 'pending') { // The state changes before pending and before resolve
        this.state = 'fulfilled'
        this.result = value
        // ⭐️⭐️ Modify parameter name parameter Meaning parameter Description Value parameter Description Value parameter Value parameter Value parameter Value parameter Value parameter Value parameter Value value
        if (this.callback.onFulfilled) { 
            this.callback.onFulfilled(this.result)
        }
      }
    }
    let reject = (reason) = > {
      if (this.state === 'pending') { Pending (reject); reject (reject
        this.state = 'rejected'
        this.result = reason;
        // ⭐️⭐️ Modify parameter name parameter Meaning parameter Description Value parameter Description Value parameter Value parameter Value parameter Value parameter Value parameter Value parameter Value value
        if (this.callback.onRejected) {
            this.callback.onRejected(this.result)
        }
      }
    }
    this.then = (onFulfilled, onRejected) = > { // then accepts two methods, resolve or reject
      if (this.state === 'pending') { // Save the callback method while waiting
        this.callback = { // ⭐️⭐ Modify ⭐ port port. This is where methods that execute asynchronously are stored
          onFulfilled,
          onRejected
        }
      }
      if (this.state === 'fulfilled') { // If the state is fufilled, perform the ondepressing method passed in
        setTimeout(() = > {
          onFulfilled(this.result)
        });
      }
      if (this.state === 'rejected') { // reject, reject, execute the passed onRejected method
        setTimeout(() = > {
          onRejected(this.result) }); }}// If a new Promise fails, try catch is required
    try {
      executor(resolve, reject) // Execute resolve or reject when new Promise is implemented
    } catch (error) {
      reject(error) // new Promise returns an error}}window.Typromise = Typromise
})()
Copy the code

The test is normal

3. Then method chain call

1. The call to the second then

Analysis:

  • 1. How to implement the second onethen? As we learned earlierthenAnd the way to do that is bynew PromiseIn theresolverejectAfter the execution.
  • 2. HandwrittenthenThere should be one in the methodPromiseTo continue to executethen
  • 3. We are inthenRun it againresolverejectIt goes on to the next onethenAnd so onthenReturns a new onePromiseAnd performresolvereject.

Modified then method

  • 1. ThethenThe inside method is usednew TypromiseWrap it up and return
  • 2. In the first onethenIn the implementationresolverejectReturn the value to the next onethen

The subscript ⭐️⭐️ is used for the modification

...this.then = (onFulfilled, onRejected) = > { // then accepts two methods, resolve or reject
 let p = new Typromise((resolve, reject) = > { // ⭐️⭐️ Change the value of the password.
    if (this.state === 'pending') { // Save the callback method while waiting
      this.callback = {
        onFulfilled,
        onRejected
      }
    }
    if (this.state === 'fulfilled') { // If the state is fufilled, perform the ondepressing method passed in
      setTimeout(() = > {
        let res = onFulfilled(this.result) // ⭐️⭐️ Change the value of the password.
        resolve(res) // ⭐️⭐️ Change the value of the password.
      });
    }
    if (this.state === 'rejected') { // reject, reject, execute the passed onRejected method
      setTimeout(() = > {
        let res = onRejected(this.result) // ⭐️⭐️ Change the value of the password.
        resolve(res) / / ⭐ ️ ⭐ ️ modify ⭐ ⭐ ️ -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 2. Why does this resolve and running results under the view}); }})return p // ⭐️⭐️ Change the value of the password.}...Copy the code

Test results:

console.log('1. -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- - written promise');
let ty = new Typromise((resolve, reject) = > {
    resolve('fulfilled - written');
    // reject('reject- write ');
    console.log('2.new Typromise')
}).then(value= > {
    return value
}, error= > { 
}).then(value= > {
    console.log('4.value: ', value);
}, error= > {
    console.log('4.error: ', error);
})
console.log('3.-----------------ty')

console.log('1. -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- the original Promise');
let p = new Promise((resolve, reject) = > {
    resolve('fulfilled - official');
    // reject('reject- official ');
    console.log('2.new Promise')
}).then(value= > {
    return value
}, error= > { 
}).then(value= > { 
    console.log('4.value: ', value);
}, error= > { 
    console.log('4.error: ', error);
})
console.log('3.-----------------p')
Copy the code

Why is it in the codethis.state === 'rejected'Also used whenresolveBecause of the default state of the new promise it was successful, even if the first onethenExecution isrejectThe method also returns success to the secondthenIt won’t affect our next onethen, you can see the following test results comparison

2. Chain calls to the third and subsequent THEN

Analysis problem:

  • 1. After the above modification, the result of the third THEN call is different. After the handwritten promise executes the second THEN, the third THEN is not executed

  • 2. I printed it in thenstateresult, found the secondthenThe start of thestateIs in thependingThe state has not changed
console.log('this.state: '.this.state);
console.log('this.result: '.this.result);
Copy the code

transformthenmethods

  • So I willthenIn thethis.state === 'pending'The method of li is also executedresolverejectReturn the value to the next onethen

Based on the above THEN code, use the subscript ⭐️⭐️ as the place to modify

...this.then = (onFulfilled, onRejected) = > { // then accepts two methods, resolve or reject
  let p = new Typromise((resolve, reject) = > {
    if (this.state === 'pending') { // Save the callback method while waiting
     // ⭐️⭐️ Modify parameter name parameter name parameter Name Parameter Name Parameter Name Parameter Name Parameter Name Parameter Name Parameter Name Parameter Name Parameter Value
      this.callback = {
        onFulfilled:value= >{
          let res = onFulfilled(this.result)
          resolve(res)
        },
        onRejected:value= >{
          let res = onRejected(this.result)
          resolve(res)
        }
      }
    }
    if (this.state === 'fulfilled') { // If the state is fufilled, perform the ondepressing method passed in
      setTimeout(() = > {
        let res = onFulfilled(this.result)
        resolve(res)
      });
    }
    if (this.state === 'rejected') { // reject, reject, execute the passed onRejected method
      setTimeout(() = > {
        let res = onRejected(this.result) resolve(res) }); }})returnP}...Copy the code

The test results

console.log('1. -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- - written promise');
let ty = new Typromise((resolve, reject) = > {
    resolve('fulfilled - written');
    // reject('reject- write ');
    console.log('2.new Typromise')
}).then(value= > {
    return value
}, error= > { 
}).then(value= > {
    return value
}, error= > { 
}).then(value= > {
    console.log('4.value: ', value);
}, error= > {
    console.log('4.error: ', error);
})
console.log('3.-----------------ty')

console.log('1. -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- the original Promise');
let p = new Promise((resolve, reject) = > {
    resolve('fulfilled - official');
    // reject('reject- official ');
    console.log('2.new Promise')
}).then(value= > {
    return value
}, error= > { 
}).then(value= > {
    return value
}, error= > { 
}).then(value= > { 
    console.log('4.value: ', value);
}, error= > { 
    console.log('4.error: ', error);
})
console.log('3.-----------------p')
Copy the code

Conclusion: As long as the return value continues to increasethenThe execution is called all the time, creating a chain call

4. The then method returns promise processing and then penetration

1. Return promise

  • Analysis: We wrote it by handpromisewhenthenIn returnpromiseNowadays athenThere is no returnvalueIt went straight backpromise

Continue to transformthenMethod to distinguish between the two types returned,Distinguish betweenreturnisTypromiseType or pure value type

Based on the above THEN code, use the subscript ⭐️⭐️ as the place to modify

this.then = (onFulfilled, onRejected) = > { // then accepts two methods, resolve or reject
  let p = new Typromise((resolve, reject) = > {
    if (this.state === 'pending') { // Save the callback method while waiting
      this.callback = {
        onFulfilled: value= > {
          let res = onFulfilled(this.result)
          // START⭐️⭐️ Modify parameter description value ️⭐ administrator resolve(res) Modify value
          if (res instanceof Typromise) {
            res.then(value= >{
              resolve(value)
            },reason= >{
              reject(reason)
            })
          } else {
            resolve(res)
          }
          // END⭐️⭐️ Modify parameter name parameter Name Parameter Meaning resolve(res) Modify parameter name
        },
        onRejected: value= > {
          let res = onRejected(this.result)
          // START⭐️⭐️ Modify parameter description value ️⭐ administrator resolve(res) Modify value
          if (res instanceof Typromise) {
            res.then(value= >{
              resolve(value)
            },reason= >{
              reject(reason)
            })
          } else {
            reject(res)
          }
          // END⭐️⭐️ Modify parameter name parameter Name Parameter Meaning resolve(res) Modify parameter name}}},if (this.state === 'fulfilled') { // If the state is fufilled, perform the ondepressing method passed in
      setTimeout(() = > {
        let res = onFulfilled(this.result)
        // START⭐️⭐️ Modify parameter description value ️⭐ administrator resolve(res) Modify value
        if (res instanceof Typromise) {
          res.then(value= >{
            resolve(value)
          },reason= >{
            reject(reason)
          })
        } else {
          resolve(res)
        }
        // END⭐️⭐️ Modify parameter name parameter Name Parameter Meaning resolve(res) Modify parameter name
      });
    }
    if (this.state === 'rejected') { // reject, reject, execute the passed onRejected method
      setTimeout(() = > {
        let res = onRejected(this.result)
        // START⭐️⭐️ Modify parameter description value ️⭐ administrator resolve(res) Modify value
        if (res instanceof Typromise) {
          res.then(value= >{
            resolve(value)
          },reason= >{
            reject(reason)
          })
        } else {
          reject(res)
        }
        // END⭐️⭐️ Modify parameter name parameter Name Parameter Meaning resolve(res) Modify parameter name}); }})return p
}
Copy the code

It can be seen that there is a lot of redundant code in the above. After the function is improved, the following test results will be optimized:

console.log('1. -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- - written promise');
let ty = new Typromise((resolve, reject) = > {
    resolve('fulfilled - written');
    // reject('reject- write ');
    console.log('2.new Typromise')
}).then(value= > {
    return new Typromise((resolve,reject) = >{
        resolve(value)
        // reject(value)})},error= > { 
}).then(value= > {
    return new Typromise((resolve,reject) = >{
        resolve(value)
        // reject(value)})},error= > { 
}).then(value= > {
    console.log('4.value: ', value);
}, error= > {
    console.log('4.error: ', error);
})
console.log('3.-----------------ty')

console.log('1. -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- the original Promise');
let p = new Promise((resolve, reject) = > {
    resolve('fulfilled - official');
    // reject('reject- official ');
    console.log('2.new Promise')
}).then(value= > {
    return new Promise((resolve,reject) = >{
        resolve(value)
        // reject(value)})},error= > { 
}).then(value= > {
    return new Promise((resolve,reject) = >{
        resolve(value)
        // reject(value)})},error= > { 
}).then(value= > { 
    console.log('4.value: ', value);
}, error= > { 
    console.log('4.error: ', error);
})
console.log('3.-----------------p')
Copy the code

2. Then pass through

  • Analysis: nativethen()Even if you pass a null value the next onethen()Also can receivepromiseIn theresolveorrejectThe value after execution, and handwriting because passed a null value directly error,So we need to be inthenDo a non-null check on the method and pass through the value

Continue to transformthenmethods

Based on the above THEN code, use the subscript ⭐️⭐️ as the place to modify

...this.then = (onFulfilled, onRejected) = > { // then accepts two methods, resolve or reject
    // START⭐️⭐️ Modify the value of the input function
    if(! (onFulfilledinstanceof Function)) {
        onFulfilled = value= > value // When null, pass the value directly to the next then
    }
    if(! (onRejectedinstanceof Function)) {
        onRejected = reason= > reason // When null, pass the value directly to the next then
    }
    // END⭐️⭐️ Modify the input function judgment
    let p = new Typromise((resolve, reject) = >{···}) ···})Copy the code

Test results:

console.log('1. -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- - written promise');
let ty = new Typromise((resolve, reject) = > {
    resolve('fulfilled - written');
    // reject('reject- write ');
    console.log('2.new Typromise')
}).then().then(value= > {
    console.log('4.value: ', value);
}, error= > {
    console.log('4.error: ', error);
})
console.log('3.-----------------ty')

console.log('1. -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- the original Promise');
let p = new Promise((resolve, reject) = > {
    resolve('fulfilled - official');
    // reject('reject- official ');
    console.log('2.new Promise')
}).then().then(value= > { 
    console.log('4.value: ', value);
}, error= > { 
    console.log('4.error: ', error);
})
console.log('3.-----------------p')
Copy the code

5. Then error processing and code redundancy optimization

1. Return the promise type constraint to prevent users from falling into an infinite loop when they return to a new promise

Such as

let p = new Promise((resolve, reject) = > {
    return p; // Returns itself here
}).then(value= > {
    return new Promise(resolve= >{
        resolve(value)
    })
}, error= >{})Copy the code

Join the inspection

if (p === res) {
    throw new TypeError('Chaining cycle detected for promise #<Typ romise>')}Copy the code

2. Error handling

Every timethenError when executing incorrect syntax intry catchTo deal withrejectOne mistake can be made by the nextThen reject ()capture

3. Encapsulate redundant code parse and paste the full code

  • encapsulationparseMethod handles redundant code
  • implementationcatch()methods

    promise.then().catch() thecatch()Method returns aPromiseAnd handle the rejection. becausethenThe second argument to the method actually does that; catch is just another name. whenthenIf the second argument to the method is absent, it automatically returnscatchTo take over

The subscript ⭐️⭐️ is used for the modification

(function () {
  function Typromise(executor) { // executor new Promise method passed in
    this.state = 'pending' // There is a promise state, which is fulfilled Rejected Pending
    this.result = ' ' // New Promise execution result
    this.callback = {} // Define an object to collect method calls
    // START⭐️⭐️ Modify disk disk disk disk Add parse encapsulation method to handle code redundancy
    let parse = (p, res, resolve, reject, type) = > {
      if (p === res) { // Returns the promise type constraint to prevent the user from falling into an infinite loop when returning to itself on a new promise
        throw new TypeError('Chaining cycle detected for promise #<Typromise>')}if (res instanceof Typromise) {
        /* res.then(value=>{ resolve(value) },value=>{ reject(value) }) */
        res.then(resolve, reject) // The above method can be abbreviated
      } else {
        type == 'resolve' ? resolve(res) : reject(res)
      }
    }
    // END⭐️⭐️ Modify the value of the link. Add the parse encapsulation method to deal with code redundancy
    // The executor passes two methods to define a new Promise: resolve,reject
    let resolve = (value) = > {
      if (this.state === 'pending') { // The state changes before pending and before resolve
        this.state = 'fulfilled'
        this.result = value
        if (this.callback.onFulfilled) {
          setTimeout(() = > {
            this.callback.onFulfilled(this.result) }); }}}let reject = (reason) = > {
      if (this.state === 'pending') { Pending (reject); reject (reject
        this.state = 'rejected'
        this.result = reason;
        if (this.callback.onRejected) {
          setTimeout(() = > {
            this.callback.onRejected(this.result) }); }}}this.then = (onFulfilled, onRejected) = > { // then accepts two methods, resolve or reject
      if(! (onFulfilledinstanceof Function)) {
        onFulfilled = value= > value // When null, pass the value directly to the next then
      }
      if(! (onRejectedinstanceof Function)) {
        onRejected = reason= > reason // When null, pass the value directly to the next then
      }
      let p = new Typromise((resolve, reject) = > {
        if (this.state === 'pending') { // Save the callback method while waiting
          this.callback = {
            onFulfilled: value= > {
              // START⭐️⭐️ Modify a trap error
              try {
                parse(p, onFulfilled(value), resolve, reject, 'resolve')}catch (error) {
                reject(error)
              }
              // END⭐️⭐️ Modify a trap error
            },
            onRejected: value= > {
              // START⭐️⭐️ Modify a trap error
              try {
                parse(p, onRejected(value), resolve, reject, 'reject')}catch (error) {
                reject(error)
              }
              // END⭐️⭐️ Modify a trap error}}},if (this.state === 'fulfilled') { // If the state is fufilled, perform the ondepressing method passed in
          setTimeout(() = > {
            // START⭐️⭐️ Modify a trap error
            try {
              parse(p, onFulfilled(this.result), resolve, reject, 'resolve')}catch (error) {
              reject(error)
            }
            // END⭐️⭐️ Modify a trap error
          });
        }
        if (this.state === 'rejected') { // reject, reject, execute the passed onRejected method
          setTimeout(() = > {
            // START⭐️⭐️ Modify a trap error
            try {
              parse(p, onRejected(this.result), resolve, reject, 'reject')}catch (error) {
              reject(error)
            }
            // END⭐️⭐️ Modify a trap error}); }})return p
    }
    // START⭐️⭐️ Modify the catch method catch error
    The catch method has only one argument to handle the error case
    this.catch = onRejected= > {
      return this.then(null, onRejected)
    }
    // END⭐️⭐️ Modify the catch method catch error
    // If a new Promise fails, try catch is required
    try {
      executor(resolve, reject) // Execute resolve or reject when new Promise is implemented
    } catch (error) {
      reject(error) // new Promise returns an error}}window.Typromise = Typromise
})()
Copy the code

6. Promise. Resolve and Promise. Reject

... Typromise. Resolve =(value) = > {
    return new Typromise((resolve, reject) = > {
      if (value instanceof Typromise) {
        value.then(resolve, reject)
      } else {
        resolve(value)
      }
    })
}
Typromise.reject = (value) = > {
    return new Typromise((resolve, reject) = > {
        reject(value)
    })
}
window.Typromise = Typromise
Copy the code

The test results Conclusion: Typromise.reject must also be asynchronous

Typromise.reject = (value) = > {
    return new Typromise((resolve, reject) = > {
        setTimeout(() = > {
            reject(value)
        })
})
Copy the code

The tests came back normal.

7.Promise.all

  • 1.Promise.all(promises)Incoming parameterspromisesIt has to be oneArray typeIf,Type stringReturns an error for any other type
  • 2.Promise.allAll requests must be successfulresolveValue, if one of them fails directlyreject
... Typromise. All =(promises) = > {
    return new Promise((resolve, reject) = > {
      if (typeof promises === 'object' && promises instanceof Array) {
        const values = [];
        promises.forEach(promise= > {
          promise.then(value= > {
            values.push(value)
            if (promises.length === values.length) { // All must succeed to resolve
              resolve(values)
            }
          }, reason= > { // Reject a failure
            reject(reason)
          })
        })
      } else {
        if (typeof promises === 'string') { // String is returned directly
          resolve(promises)
        } else {
          throw new TypeError(typeof promises + ' ' + promises + ' is not iterable (cannot read property Symbol(Symbol.iterator))')}}})}window.Typromise = Typromise
Copy the code

Test results:

8.Promise.race

  • 1.Promise.race(promises)Incoming parameterspromisesIt has to be oneArray typeIf,Type stringReturns an error for any other type
  • 2.Promise.raceWhichever request succeeds returns the faster value, and whoever fails first also ends up with the result of failure directly
Typromise.race = (promises) = > {
    return new Promise((resolve, reject) = > {
      if (typeof promises == 'object' && promises instanceof Array) {
        const values = [];
        promises.forEach(promise= > {
          promise.then(value= > {
            resolve(value)
          }, reason= > {
            reject(reason)
          })
        })
      } else {
        if (typeof promises == 'string') { // String is returned directly
          resolve(promises)
        } else {
          throw new TypeError(typeof promises + ' ' + promises + ' is not iterable (cannot read property Symbol(Symbol.iterator))')}}})}window.Typromise = Typromise
Copy the code

The last

Above way to summarize their learning summary, there are other ways a, welcome each big comment on Tony welcome each big god more correct, not praise, supervision and correct ( ̄.  ̄) for the relevant articles are often asked about the interview can help you stay, the younger brother can complement to perfect the exchange of learning together, thank you for your bosses (~  ̄ del  ̄) ~