The use of the Promise

  1. The easiest way to use promise is:
const p1 = new Promise((resolve,reject) = > {
	console.log('Create a Promise')
	resolve('It worked')   
    // If the operation succeeds,
    // The resolve argument will be the argument to.then (successful callback)
})

	console.log('after new Promise')

const p2 = p1.then(
	(data) = > {
    	console.log(data)
        throw new Error('Failed')}Resolve => {}
)

const p3 = p2.then(
	(data) = > {
    	console.log('success',data)
    },
    (err) = > {
    	console.log('failed',err)   // Because the previous step threw an Error, the Error message is printed here})// Console print:To create aPromise
after new PromiseSuccessful failedErrorFailed:Copy the code
  • By default, the state is pending. If the state changes to success one day, it succeeds. If the state changes to failure, it fails. Calling both resolve and reject takes the result of the first call by default

  • If the previous then returns a normal value (not an error, not a Promise), then the next successful callback (undefined) will be executed. If the previous then returns a Promise, then the Promise will modify the state of the next callback to determine which callback to execute. Success or failure.

  • Note that the executor body above writes synchronous operations. If the operation is asynchronous, then the Promise state remains pedding

  • If pedding is still in the status of.then, the successful and failed callbacks should be stored in their respective queues and executed in resolve or Reject after the request result is returned.

  • In handwritten Promise implementation, setTimeout is used to realize the asynchrony of the Promise.

  • Since the native Promise is a microtask provided by the V8 engine, we cannot restore the implementation of the V8 engine, so setTimeout is used here to simulate asynchronous, so the native is the microtask, and here is the macro task.

@Zhihu Qi Little God

Write a promise


const resolvePromise = (promise2, x, resolve, reject) = > {
  // Waiting for yourself to finish is A bad implementation, end with A type error
  if (promise2 === x) { 
    return reject(new TypeError('Chaining cycle detected for promise #<Promise>'))}// Promise/A+ 2.3.3.3.3 can only be called once
  let called;
  // Subsequent conditions must be strictly judged to ensure that the code can be used with other libraries
  if ((typeof x === 'object'&& x ! =null) | |typeof x === 'function') { 
    try {
      Reject (reject and resolve) Promise/A+ 2.3.3.1
      let then = x.then;
      if (typeof then === 'function') { 
        DefineProperty Promise/A+ 2.3.3.3
        then.call(x, y= > { // Success or failure depends on the state of the promise
          if (called) return;
          called = true;
          // Recursive resolution process (because there may still be promises in promises) Promise/A+ 2.3.3.3.1
          resolvePromise(promise2, y, resolve, reject); 
        }, r= > {
          // As long as I fail, I fail
          if (called) return;
          called = true;
          reject(r);
        });
      } else {
        // If x. Chen is A normal value, return resolve as A result. Promise/A+ 2.3.3.4resolve(x); }}catch (e) {
      / / Promise/A + 2.3.3.2
      if (called) return;
      called = true;
      reject(e)
    }
  } else {
    // If x is A normal value, resolve is returned as the result. Promise/A+ 2.3.4
    resolve(x)
  }
}

class myPromise {
	constructor(executor){
		this.state = 'pedding'
		this.value = undefined
		this.reason = undefined

		this.onFullfilledList = []
		this.onRejectedList = []


		let resolve = (value) = > {
			if(this.state === 'pedding') {this.state = 'success'
				this.value = value

				this.onFullfilledList.forEach(fn= > fn())
			}
		}

		let reject = (reason) = > {
			if(this.state === 'pedding') {this.state = 'failed'
				this.reason = reason

				this.onRejectedList.forEach(fn= > fn())
			}
		}

		try {
			executor(resolve,reject)
		}catch(error){
			reject(error)
		}
	}


	then(onFullfilled,onRejected) {
		onFullfilled = typeof onFullfilled === 'function' ? onFullfilled : v= > v
		onRejected = typeof onRejected === 'function' ? onRejected : err= > {throw err}

		let promise2 = new Promise((resolve,reject) = > {
			if(this.state === 'success') {setTimeout(() = >{
					try {
						let x = onFullfilled(this.value)

						resolvePromise(promise2,x,resolve,reject)
					}catch(err){
						reject(err)
					}
				},0)}if(this.state === 'failed') {setTimeout(() = >{
					try{
						let x = onRejected(this.reason)

						resolvePromise(promise2,x,resolve,reject)
					}catch(err){
						reject(err)
					}
				},0)}if(this.state === 'pedding') {this.onFullfilledList.push(() = >{
						setTimeout(() = >{
							try {
								let x = onFullfilled(this.value)

								resolvePromise(promise2,x,resolve,reject)
							}catch(err){
								reject(err)
							}
						},0)})this.onRejectedList.push(() = >{
					setTimeout(() = >{
						try{
							let x = onRejected(this.reason)

							resolvePromise(promise2,x,resolve,reject)
						}catch(err){
							reject(err)
						}
					},0)})}})return promise2
	}	
}

const resolvePromise = function(promise2,x,resolve,reject){}Copy the code

Promise Api

Promise. Resolve () returns a successful Promise. Reject () returns a failed Promise. Promise.race(arr) takes the state of the fastest returned result promise.prototype. catch((e)=>{}) catches an error, if it doesn’t have its own failure handler, walk the catch

Promise.all

  • Only all of the parameterspromisereturnresolve, will returnresolve
  • One of the parameters failedrejected, it returnsrejectedThe reason is the first failurerejectedThe results of the


Promise.all1 = function(arr){
	if(!Array.isArray(arr)){
		return new TypeError('err')}return new Promise((resolve,reject) = >{
		let resArr = []
		let count = 0
		const processRes = (value,index) = > {
			resArr[index] = value
			if(++count === arr.length){
				resolve(resArr)
			}
		}

		for(let i = 0; i < arr.length; i++){
			if(arr[i] && typeof arr[i].then === 'function'){
				arr[i].then((value) = >{
					processRes(value,i)
				},reject)
			}else{
				processRes(arr[i],i)
			}
		}
	})

}
Copy the code

Promise.race

Promise.race = function(arr){
	return new Promise((resolve,reject) = >{
		for(let i = 0; i < arr.length; i++){
			if(arr[i] && typeof arr[i].then === 'function'){
				arr[i].then((value) = >{
					resolve(value)
				})
			}else{
				resolve(arr[i])
			}
		}
	})
}
// This is easy thanks to the fact that the promise state can only be changed once, meaning that resolve and reject can only be implemented once
Copy the code

Common problems:

  1. What problem did Promise solve? (Callback hell, of course)
  2. What are the Promise implementations?
  3. What are the common apis?
  4. Write a Promise?
  5. How does a Promise perform in an event loop?
  6. What are the defects of Promise and how to solve them?

Q&A_1: What problem does Promise solve?

  • Nesting of asynchronous requests in which subsequent functions depend on the results returned by previous functions
  • When multiple asynchronous requests are concurrent, development often needs to synchronize the final result of the request

Solution:

  • The Promise chain calls solve callback hell
  • Promise.all gets error handling for multiple tasks

New Promise() takes an Executor function as an argument, writes the request in the function body, executes immediately, gets the request result, changes the Pedding state, changes the Pedding state if the request succeeds, changes the Pedding state if the request fails, and then uses the. Then method. Retrieve return results (successful data and failed ERR)

Promise error handling promise.reject () directly converts the value into an error result promise.prototype.catch, which catches a promise exception, equivalent to an unsuccessful then promise. Prototyoe. Finally, the finally said anyway, if return failure, will spread to catch