Interviewer: “Can you make a Promise by hand?”

The reason for Promise & industry implementation

Before promises, code used to look like this when we were dealing with multiple nested asynchronous requests

let fs = require('fs')

fs.readFile('./name.txt'.'utf8'.function(err,data){
  fs.readFile(data, 'utf8'.function(err,data){
    fs.readFile(data,'utf8'.function(err,data){
      console.log(data); })})})Copy the code

Promise came along and gave us the perfect hell callback solution.

let fs = require('fs')

function read(filename) {
  return new Promise((resolve, reject) = > {
    fs.readFile(filename, 'utf8'.(err, data) = > {
      if (err) reject(err);
      resolve(data);
    })
  })
}

read('./name.txt').then((data) = >{
  return read(data) 
}).then((data) = >{
  return read(data)  
}).then((data) = >{
    console.log(data);
},err= >{
    console.log(err);
})
Copy the code

Use of Promise

Let’s review the simplest way to use promises:

const p1 = new Promise((resolve, reject) = > {
  console.log('create a promise');
  resolve('It worked');
})

console.log("after new promise");

const p2 = p1.then(data= > {
  console.log(data)
  throw new Error('Failed')})const p3 = p2.then(data= > {
  console.log('success', data)
}, err= > {
  console.log('faild', err)
})
Copy the code
"create a promise"
"after new promise"
"It worked"
"Faild Error: Failed"
Copy the code

Promise basic features

  1. Promise has three states:pending.fulfilled, orrejected; “Specification Promise/A+ 2.1”
  2. When you make a new promise, you need to pass oneexecutor()Actuator, actuatorExecuted immediately;
  3. Executor takes two arguments, one of which isresolveandreject;
  4. The default state for promise ispending;
  5. There’s one promisevalueThe value of the saved status, which can beundefined/thenable/promise; “Specification Promise/A+ 1.3”
  6. There’s one promisereasonSave the value of the failed state; “Specification Promise/A+ 1.5”
  7. Promise only frompendingtorejected, or frompendingtofulfilledOnce the state is confirmed, it will not change;
  8. There must be a promisethenMethod,thenReceive two arguments, one for the promise’s successful callbackonFulfilled, and the promise failed callbackonRejected; “Specification Promise/A+ 2.2”
  9. If the promise has been successful by the time then is called, it is executedonFulfilledThe argument is promise’svalue;
  10. If the promise has failed by the time then is called, it is executedonRejectedThe argument is promise’sreason;
  11. If an exception is thrown in then, it is passed as an argument to the failed callback of the next THENonRejected;

Basic version of the Promise

const PENDING = 'PENDING';
const FULFILLED = 'FULFILLED';
const REJECTED = 'REJECTED';
class Promise{
  constructor(executor){
    this.status=PENDING;
    this.value=undefined;
    this.reason=undefined;
    // Calling this method succeeds
    let resolve=(value) = >{
      if(this.status===PENDING){
        this.status=FULFILLED;
        this.value=value; }}// Calling this method fails
    let reject=(reason) = >{
      if(this.status===PENDING){
        this.status=REJECTED;
        this.reason=reason; }}try{
    Execute immediately, passing the resolve and reject functions to the consumer
      executor(resolve,reject)
    }catch(error){
      reject(error)
    }
  }
  // Include a THEN method and accept two parameters onFulfilled and onRejected
  then(onFulfilled, onRejected){
    if(this.status===FULFILLED){
      onFulfilled(this.value)
    }else if(this.status===REJECTED){
      onRejected(this.reason)
    }
  }
}
const promise = new Promise((resolve, reject) = > {
  resolve('success');
}).then(
  (data) = > {
    console.log('success', data)
  },
  (err) = > {
    console.log('faild', err)
  }
)/ / success
Copy the code

Written promise. All

function diPromiseAll(promises){
    return new Promise((resolve, reject) = >{
        // Determine the parameters
        if(!Array.isArray(promises)){
            throw new TypeError("promises must be an array")}let result = [] // Store the result
        let count = 0 // Record several resolved messages
        promises.forEach((promise, index) = > {
            promise.then((res) = >{
                result[index] = res
                count++
                count === promises.length && resolve(result) // Determine if it is completed
            }, (err) = >{
                reject(err)
            })
        })
    })
}
Copy the code

Validation:

let p1 = Promise.resolve(1),
    p2 = Promise.resolve(2),
    p3 = Promise.resolve(3);

diPromiseAll([p1, p2, p3]).then((res) = >{
    console.log(res, 'res')},(err) = >{
    console.log(err, 'err')})/ / [1, 2, 3]
Copy the code

Written Promise. Race

function promiseRace([...promises]){
  return new Promise((resolve,reject) = >{
    promises.forEach((promise) = >{
      promise.then((res) = >{
        resolve(res)
      },(err) = >{
        reject(err)
      })
    })
  })
}
promiseRace([promise1,promise2,promise3]).then((res) = >{
  console.log(res);
}).catch((err) = >{
  console.log(err)
})
Copy the code