Promise

features

Create an instance

One: created using a constructor, which accepts a callback function that passes in the resolve and reject methods

const promise = new Promise((resolve, reject) = > {
  resolve('data')
})

promise.then((data) = > {
  console.log(data)                         // data, then print
})

console.log(promise instanceof Promise)     // true, print first
Copy the code

The advantage of this approach is that it is flexible and allows you to control the additional actions you can take when creating a Promise instance, but the code is cumbersome

The code executes the constructor synchronously, and only asynchronously when it starts the chain call

Two: create using static methods promise.resolve () or promise.reject ()

const promise = Promise.resolve('data')
promise.then((data) = > {
  console.log(data)       // data
})
Copy the code

Promise.resolve() is the syntactic sugar of new Promise((resolve) => {resolve()}), and does exactly the same thing

During the chain invocation of a Promise, each chain invocation of a chained method (resolve, Reject, THEN, Catch, finally) returns a brand new Promise instance, so this method can naturally be used as a Promise creation

Declare that the instance is a synchronous operation, and the asynchronous task will only be created when the chain call is initiated

const promise = new Promise((resolve) = > {
  resolve('promise')})const promiseTask = promise.then(() = > 'promiseTask')

console.log('Synchronization task starts..... ')
console.log('promise:')
console.log(promise)
console.log('promiseTask:')
console.log(promiseTask)

setTimeout(() = > {
  console.log('Asynchronous task starts..... ')
  console.log('promise:')
  console.log(promise)
  console.log('promiseTask:')
  console.log(promiseTask)
})
Copy the code


State changes

Promise has three states:

  • Pending: Pending
  • Resolved: Resolved (also known as Resolvedfulfilled)
  • Rejected: It has failed

There are only two types of state changes:

  • Pending → Resolved
  • Pending → Rejected

When a promise state passes from pengding to another arbitrary state, the promise state remains in that state and cannot be changed

If no errors occur in chain calls, they are all pending → Resolved state transitions


Asynchronous blocking

In a chained call to a promise, the state of the previous promise is set to non-pending before the next promise is executed. Note that blocking only works for promises and does not directly apply to other asynchronous functions

Promise.resolve()
  .then(() = > {
    setTimeout(() = > {
      console.log('setTimeout method executed')
    })
  })
  .then(() = > {
    console.log('Mission completed')})Copy the code

If you want to block these tasks you need to encapsulate them with promises

Promise.resolve()
  .then(() = > {
    return new Promise((resolve) = > {
      setTimeout(() = > {
        console.log('setTimeout method executed')
        resolve()
      })
    })
  })
  .then(() = > {
    console.log('Mission completed')})Copy the code


The data transfer

The data delivery of a promise can only accept the previous data by the next chain call, not across levels

Promise.resolve('A')
  .then((data) = > {
    console.log(data)				// A
    return 'B'
  })
  .then((data) = > {
    console.log(data)				// B
  })
Copy the code

The then callback uses return to pass the result, whereas Promise passes resolve because the compiler resolves the value of return in then to return promise.resolve (…). “Returns a new promise instance


Error handling

Promise uses reject and catch to catch errors

The Reject method returns a promise of a failed state, which is used to throw an error

const promise =  Promise.resolve().then(() = > {
  return new Promise((resolve, reject) = > {
    reject('Big deal!! ')})})console.log(promise)

setTimeout(() = > {
  console.log(promise)
})
Copy the code

The catch method returns a promise of success status, which is used to handle errors

const promise =  Promise.resolve().then(() = > {
  throw new Error('Big deal!! ')
})
  .catch((err) = > {
    console.log(err)
    return 'Error message'
  })

console.log(promise)

setTimeout(() = > {
  console.log(promise)
})
Copy the code

Association relation:

  • After the previous promise is set to reject, its data is passed to the second callback of the next THEN method. If the callback is not declared, the data is captured by the subsequent catch method
  • If the error is caused by a network, the error can only be caught by a catch

So we usually just use the catch method

const promise =  Promise.reject('Big deal!! ')
  .then(
    (data) = > {console.log(data)},      // No data is printed
    (err) = > {console.log(err)}         // Something is wrong!!
  )
Copy the code
const promise =  Promise.reject('Big deal!! ')
  .then(
    (data) = > {},      
    (err) = > {}                
  )
  .catch((err) = > {
    console.log(err)                    // No data is printed because the error was caught earlier
  })
Copy the code

Processing order: If one of the promises is put in a failed state, the promise task before the error is caught will not be executed

// > tasks 3, 4 will not be executed, using the second callback function of then to catch the same error function
Promise.resolve()
  .then(() = > {console.log('Perform the first task')})
  .then(() = > {
    console.log('Perform the second mission')
    throw new Error('Big deal!! ')
  })
  .then(() = > {console.log('Perform the third mission')})
  .then(() = > {console.log('Run the fourth mission')})
  .catch((err) = > {
    console.log('Run the fifth mission')
    console.log(err)
  })
  .then(() = > {console.log('Run the sixth mission')})
  
Copy the code

If there are more than one error, then catch the error → catch the first error in the process

Promise.reject('Big deal!! ')
  .then(() = > {
    throw new Error('Big deal again!! ')
  })
  .catch((err) = > {
    console.log(err)                      // Something is wrong!!
  })
  .catch((err) = > {
    console.log(err)                      // No data is printed
  })
  .then(() = > {
    throw new Error('Big deal again!! ')
  })
  .catch((err) = > {
    console.log(err)                      // Again big trouble!!
  })
  
Copy the code

Promise method

Chain calls

promise.then (callback? , errorCallback?)

  • Function: Chain calls the next task
  • Parameters:
    • callback? : function(data):
      • Data: Data passed when the last promise was successful
    • errorCallback? : function(error):
      • Error:Error → catchThe initial mistake in the process
  • The return value:Promise: Returns a new promise
Promise.resolve('Data passed')
  .then((data) = > {
    console.log(data)       // The data passed
  })
  .then((data) = > {
    console.log(data)       // undefined because the previous promise did not pass a value
  })
Copy the code

promise.catch (callback?)

  • Function: Catch errors during chained tasks
  • Parameters:
    • callback? : function(error):
      • Error:Error → catchThe initial mistake in the process
  • The return value:Promise: Returns a new promise
Promise.reject('Big deal!! ')
  .catch((err) = > {
    console.log(err)      // Something is wrong!!
  })
Copy the code

promise.finally (callback?)

  • Function: Executes this method regardless of whether there is an error in the task chain
  • Parameters:
    • callback? : function(): Execution content
  • The return value:Promise: Returns a new promise
new Promise((resolve, reject) = > {
  resolve()
})
  .then(() = > new Promise((resolve, reject) = > {
    reject()
  }))
  .finally(() = > {
    console.log('Mission accomplished')       // Mission completed
  })
Copy the code

Parallel processing

Promise.all (promiseTasks)

  • Function: Parallel processing of multiple promise tasks, only all promises are successful promise returned will be successful, otherwise fail
    • On success, the data from each promise is stored in an array in the order of the task declaration and passed to the next promise
    • When it fails, the first failed promise error message is passed to the next promise
  • Parameters:
    • promiseTasks: Array<Promise>: PROMISE Task set
  • The return value:Promise: Returns a new promise that contains an array of data for all successful tasks, or information about the first failed task

Each promise is independent during parallel processing, so the failure of one promise does not affect other promises, only the outcome of the parallel function

// > Print 1, 5, and 10 sequentially, indicating that the tasks are processed in parallel
const delay = (time, callback) = > new Promise((resolve) = > {
  setTimeout(() = > {
    callback()
    resolve(time)
  }, time)
})

const result = Promise.all([
  delay(10.() = > {console.log(10)}),
  delay(1.() = > {console.log(1)}),
  delay(5.() = > {console.log(5)}),
])

result.then((data) = > {
  console.log(data)       // [10, 1, 5]
})
Copy the code

Promise.all blocks all tasks on success until all tasks succeed, but if any task fails, it immediately jumps out of the method and proceeds down the chain. (This does not affect the continuation of the Promise task set within promise.all)

// > Order print big things!! 1, 5, 10, indicating that promise. all immediately exits the chain call to the next task when it fails
const result = Promise.all([
  delay(10.() = > {console.log(10)}),
  delay(1.() = > {console.log(1)}),
  Promise.reject('Big deal!! '),
  delay(5.() = > {console.log(5)}),
  Promise.reject('Big deal again!! '),
])

result.then(
  () = > {},
  (err) = > {console.log(err)}       // Something big has happened!!
)
Copy the code

Promise.race (promiseTasks)

  • Function: Handle multiple promise tasks in parallel. If one promise is not in a pengding state, it will immediately jump out of the method and go down the chain. (Other tasks that are still being executed will not be interrupted and continue to be executed.)
  • Parameters:
    • promiseTasks: Array<Promise>: PROMISE Task set
  • The return value:Promise: Returns a new promise, passing data for the first successful or failed task
// > Print 1, 5, and 10 sequentially
const delay = (time, callback) = > new Promise((resolve) = > {
  setTimeout(() = > {
    callback()
    resolve(time)
  }, time)
})

const result = Promise.race([
  delay(10.() = > {console.log(10)}),
  delay(1.() = > {console.log(1)}),
  delay(5.() = > {console.log(5)}),
])

result.then((data) = > {
  console.log(data)       / / 1
})
Copy the code

Promise.allSettled (promiseTasks)

  • Function: Handles multiple promise tasks in parallel, and only if all promises are in a non-penging state will the call continue down the chain
  • Parameters:
    • promiseTasks: Array<Promise>: PROMISE Task set
  • The return value:Promise: Returns a new Promise, passing all promise task information
// > Print 1, 5, and 10 sequentially
const delay = (time, callback) = > new Promise((resolve) = > {
  setTimeout(() = > {
    callback()
    resolve(time)
  }, time)
})

const result = Promise.allSettled([
  delay(10.() = > {console.log(10)}),
  delay(1.() = > {console.log(1)}),
  Promise.reject('Big deal!! '),
  delay(5.() = > {console.log(5)}),
  Promise.reject('Big deal again!! '),
])

result.then((data) = > {
  console.log(data)       
})
Copy the code


Use skills

The time delay function

Making a delay function with promise can be placed in the Promise task chain or async function to block asynchronous operations

// Print 1, 2, 3 sequentially
const delay = (time, callback) = > new Promise((resolve) = > {
  setTimeout(() = > {
    callback()
    resolve()
  }, time)
})

const fn = async() = > {console.log(1)
  await delay(50.() = > {console.log(2)})
  console.log(3)
}

fn()
Copy the code

Timeout handling

The promise.race feature allows you to make a timeout handler, often used in network request timeouts

Native Promises cannot cancel or interrupt a task in progress directly, but can only prevent the delivery of data by reporting an error

// Print 1, 2, 3 sequentially
const delay = (time, callback) = > new Promise((resolve) = > {
  setTimeout(() = > {
    callback()
    resolve()
  }, time)
})

Promise.race([
  delay(500.() = > {console.log(End of request)}),      // The simulated request takes 500ms
  delay(300.() = > {throw new Error('Request timed out')})])Copy the code