Promise.all()

The promise.all () method accepts an iterable of promises. Array, Map, and Set are all ES6 iterable types), and only one Promise instance is returned. The result of the resolve callbacks to all of those entered promises is an Array.

The Promise’s resolve callback is executed when all the incoming Promise’s resolve callbacks have ended, or when no promises are left in the input iterable. Its Reject callback execution throws an error as soon as any incoming promise’s Reject callback is executed or an invalid promise is entered, and reject is the first error message thrown.

Simple understanding: success in all, failure in one

For example,

Promise.all([1.2.3.new Promise((resolve, reject) = > {
 resolve('success')}),new Promise((resolve, reject) = > {
 resolve('failure')
})
]).then(values= > {
 console.log('success', values)
}).catch(e= > {
 console.log('e', e)
})
/ / the result
// Success [1, 2, 3, 'success ',' failure ']
Copy the code

If we change the result of the last Promise to reject, i.e

Promise.all([1.2.3.new Promise((resolve, reject) = > {
 resolve('success')}),new Promise((resolve, reject) = > {
 reject('failure')
})
]).then(values= > {
 console.log('success', values)
}).catch(e= > {
 console.log('e', e)
})
/ / the result
// select * from ' ';
Copy the code

Here’s how to write promise.all by hand

First we need to determine if the pass-value type in the promise. all parameter array is a Promise

function isPromise (value) {
 if (typeof value === 'function'| | -typeof value === 'object'&& value ! = =null)) {
   if (typeof value.then === 'function') {
     return true}}return false
}
Copy the code

Here’s how promise.all is implemented

Promise.all = function (values) {
 return new Promise((resolve, reject) = > {
   // result[3] = 2 result.length = 4, so we can't simply use result.length to determine whether all promises are fulfilled
   let result = []
   let times = 0;
   const postSuccess = (i, value) = > {
     result[i] = value
     if (++times === values.length) {
       resolve(result)
    }
  }
   for (let i = 0; i < values.length; i++) {
     const current = values[i]
     if (isPromise(current)) {
       current.then(value= > {
         postSuccess(i, value)
      }).catch(e= > {
         reject(e)
      })
    } else {
       postSuccess(i, current)
    }
  }
})
}
Copy the code

Promise.race()

The promise.race (iterable) method returns a Promise that is resolved or rejected once a Promise in the iterator is resolved or rejected.

Simple understanding: There is a success or failure to adopt it as a result

Although ** promise.race (iterable)** doesn’t use many scenarios, we can use it to do some simple timeout handling

If one of the methods is completed, the others are still executed, but the results are not taken

Promise.race = function (values) {
 return new Promise((resolve, reject) = > {
   for (let i = 0; i < values.length; i++) {
     const current = values[i]
     if (isPromise(current)) {
       current.then(resolve, reject)// Stop when you succeed
    } else {
       resolve(current)
    }
  }
})
}
Copy the code

test

let p1 = new Promise((resolve, reject) = > {
 setTimeout(() = > {
   resolve('success')},4000)})let p2 = new Promise((resolve, reject) = > {
 setTimeout(() = > {
   reject('failure')},2000)})Promise.race([p1, p2]).then(values= > {
 console.log('success', values)
}).catch(e= > {
 console.log('e', e)
})
// You can modify the p1 and P2 result tests
Copy the code

Actual application, picture loading timeout problem, script loading timeout problem

// How do I terminate a promise
// Race is characterized by failure and failure, so we can construct our own Promise and put it together with the original Promise
let p = new Promise((resolve, reject) = > {
 setTimeout(() = > {
   resolve(123);
}, 3000);
})
function wrap (promise) {
 let abort;
 let newPromise = new Promise((resolve, reject) = > {
   // Creates a promise that exposes a terminal method
   abort = reject;
});
 let p = Promise.race([newPromise, promise]);
 p.abort = abort;
 return p;
}
let p1 = wrap(p);
setTimeout(() = > {
 // Make this promise fail
 p1.abort(I'm out of 2s.);
}, 2000);
p1.then(data= > {
 console.log(data);
}).catch(err= > {
 console.log(err);
});
Copy the code

Promise.prototype.finally()

The finally() method returns a Promise. At the end of the promise, the specified callback function will be executed, whether the result is fulfilled or Rejected. This provides a way for code to be executed after a Promise is successfully completed or not.

This avoids the need to write the same statement once in both then() and catch().

The finally feature executes anyway, but if a promise is returned, wait for the promise to finish before continuing

For example,

let p1 = new Promise((resolve, reject) = > {
 setTimeout(() = > {
   resolve('It worked')},2000)
}).finally(() = > {// => then, execute regardless of state
 console.log('finally')
}).then(data= > {
 console.log('data', data)
})
// finally
// Data succeeds
Copy the code

Then so finally is essentially a then

implementation

Promise.prototype.finally = function (cb) {
  return this.then((data) = > {
    // How to ensure that promise.then is executed
    return Promise.resolve(cb()).then((n) = > data);
  }, (err) = > {
    // promise. resolve the purpose is to wait for the Promise execution after cb() to complete
    return Promise.resolve(cb()).then((n) = > { throwerr }); })}Copy the code