The basic part mainly introduces the basic use methods and characteristics of Promise, and the advanced part talks about the complex use of Promise.

Promise chain and Promise composite

Promise chain

Since each Promise instance returns a new Promise object, and the returned Promise object has its own instance method, the method of the returned Promise instance is called to generate a new Promise object, and then its method is called. This concatenated method call is the Promise chain.

function delayedExecute(str, callback = null) {
    setTimeout(() = > {
        console.log(str)
        callback && callback()
    }, 1000)
}
delayedExecute('p1 callback'.() = > {
    delayedExecute('p2 callback'.() = > {
        delayedExecute('p3 callback'.() = > {
            delayedExecute('p4 callback'.() = >{})})})// p1 callback (1 second later)
// p2 callback (2 seconds later)
// p3 callback (3 seconds later)
// p4 callback (4 seconds later)
Copy the code

Use Promise chains to solve this callback-dependent hell problem:

function delayedExecute(str) {
    return new Promise((resolve, reject) = > {
        console.log(str)
        setTimeout(resolve, 1000)
    })
}
delayedExecute('p1 excutor')
    .then(() = > delayedExecute('p2 excutor'))
    .then(() = > delayedExecute('p3 excutor'))
    .then(() = > delayedExecute('p4 excutor'))
    
// p1 excutor (1 SEC later)
// p2 excutor (2 seconds later)
// p3 excutor (3 seconds later)
// p4 excutor (4 seconds later)
Copy the code

Promise figure

Because a Promise can have multiple handlers, Promise chains can build directed acyclic graph structures. Each Promise instance is a vertex along the way, and handlers added using the instance method are directed vertices. Because each node in the diagram waits for the previous node to settle, the direction of the diagram is the order in which promises are resolved or rejected.

Here’s a Promise to represent a Promise digraph, or binary tree:

// A
/ / / /
// B C
// / \ /
// D E F G

let A = new Promise(resolve= > {
    console.log('A')
    resolve()
})
let B = A.then(() = > console.log('B'))
let C = A.then(() = > console.log('C'))

B.then(() = > console.log('D'))
B.then(() = > console.log('E'))
C.then(() = > console.log('F'))
C.then(() = > console.log('G'))

// A
// B
// C
// D
// E
// F
// G
Copy the code

The Promise chain represents a binary tree because Promise handlers are added to the message queue and then executed one by one, thus forming a sequential traversal of the binary tree.

Promise.all()

This static method takes an iterable and returns a new Promise object, also known as a synthetic Promise object.

Syntax: promise. all([arg1, arg2… )

Features:

  • The elements in the iterable are converted to a Promise object via promise.resolve ().

  • An empty iterable is equivalent to promise.resolve ().

  • Not passing in an iterable throws a type error.

  • The synthesized object is resolved:

    • Only when iterableallElements of thePromiseObjects areresolvedThe composite object willresolved.
    • Synthesized objectresolvedResultAll values arePromiseThe object’sresolvedResultAnd the order of the array is the order of the elements in the iterable.
  • The synthesized object is in a pending state:

    As long as one of the iterable’s elements is in a pending state, the synthesized object’s state is pending.

  • The synthesized object is in the Rejected state:

    • As long as there are elements in the iterableA PromiseThe object isrejectedState, then the state of the synthesized object isrejected.
    • Synthesized objectrejectedResultThe value isThe first Rejected objecttherejectedResult.
    • behindThe rejected Promise objectWill not affect therejectedOf the composite objectrejectedResultValue.
    • syntheticPromiseObject silently handles all containmentrejectedthePromiseObject operations,That is, no more exceptions are thrown.
    let p1 = Promise.all([
        Promise.reject(1),
        new Promise((null, reject) = > {
            setTimeout(reject, 0.2)})])let p2 = p1.catch(err= > {
        console.log(err) / / 1
    })
    console.log(p1) // Promise <rejected>: 1
    console.log(p2) // Promise <fulfilled>: undefined
    Copy the code

Promise.race()

This static method takes an iterable and returns a new Promise object, also known as a wrapped Promise object, which is the first Promise mirror in a set of collections to resolve h or reject.

Features:

  • Elements in the iterable pass throughPromise.resolve()convertPromiseObject.
  • An empty iterable is equivalent tonew Promise(() => {}).
  • Incoming non-iterable objects are thrownTypeError.
  • Promise.race()It’s a game, as the name suggests, onlyThe first oneWe get to a settled state(Pending -> resolved or pending -> Rejected)thePromiseObjects are wrapped asResults the Promise. Whatever the first state isresolvedorrejected, the rest of the rest will be ignored. If the first resting state is zerorejectedAnd the others in the backrejectedStates are handled silently and no exceptions are thrown.

Serial Promise synthesis

Concatenating Promise objects based on subsequent Promise objects using the return values of previous Promise objects is a basic Promise function.

function addTwo(x) {
    return x + 2
}
function addThree(x) {
    return x + 3
}
function addFive(x) {
    return x + 5
}

//
function addTen_1(x) {
    return addFive(addThree(addTwo(x)))
}

/ / use the Promise
function addTen_2(x) {
    return Promise.resolve(x)
        .then(addTwo)
        .then(addThree)
        .then(addFive)
}

// Use Promise and array.prototype.reduce ()
function addTen_3(x) {
    return [addTwo, addThree, addFive].reduce((promise, fn) = > promise.then(fn), Promise.resolve(x))
}
    
// Extract generic functions
fucntion compose(. fns) {
    return (x) = > fnx.reduce((promise, fn) = > promise.then(fn), Promise.resolve(x))
}
Copy the code

Promise to expand

Promise to cancel

class CancelToken {
  constructor(cancelFn) {
    this.promise = new Promise((resolve, reject) = > {
      cancelFn(() = > {
        setTimeout(console.log, 0.'delay cancelled')
        resolve()
      })
    })
  }
}

const startBtn = document.getElementById('start')
const cancelBtn = document.getElementById('cancel')

function cancellableDelayedResolve(delay) {
  setTimeout(console.log, 0.'set delay')

  return new Promise((resolve, reject) = > {
    const id = setTimeout((() = > {
      setTimeout(console.log, 0.'delay resolve')
      resolve()
    }), delay)

    const cancelToken = new CancelToken(cancelCallback= > cancelBtn.addEventListener('click', cancelCallback))
    cancelToken.promise.then(() = > clearTimeout(id))
  })
}

startBtn.addEventListener('click'.() = > cancellableDelayedResolve)
Copy the code

Promise progress notification