← Back
前端开发 2025.03.08

In-depth Understanding of ES6 011 [Learning Notes]

前端开发

Table of Contents

Promise and Asynchronous Programming

Because the execution engine is single-threaded, it needs to track the code that is about to run. That code is placed in a task queue. Whenever a piece of code is ready to execute, it is added to the task queue. Whenever a piece of code in the engine finishes execution, the event loop executes the next task in the queue.

Promise acts as a placeholder for the result of an asynchronous operation. It doesn’t subscribe to an event, nor does it pass a callback function to the target function. Instead, it makes the function return a Promise, like this:

// readFile承诺在未来的某个刻完成
let promise = readFile('txx.txt')

Promise Lifecycle

  • pending
  • fulfilled (Success)
  • rejected (Program error or some other reason)

The [[PromiseState]] internal property is used to represent the three states of a Promise. This property is not exposed on the Promise object, so the state of a Promise cannot be programmatically detected. Only when the Promise state changes can specific actions be taken via the then() method. Therefore, all Promises have a then method, which accepts two arguments: two callback functions for when it is fulfilled and when it is rejected.

If an object implements the then method mentioned above, we call that object a thenable object. All Promise objects are thenable objects, but not all thenable objects are Promises.

let promise = readFile("example.txt");
promise.then(function(contents){
  // 完成
},function(err){
  // 拒绝
})
promise.then(function(contents){
  // 完成
})

promise.then(null,function(err){
  // 拒绝
})
// catch等同于上面这种
promise.catch(function(err){
  // 拒绝
})

If a Promise is passed to the Promise.resolve() method or the Promise.reject() method, that Promise will be returned directly.

Rejection Handling in Node.js Environment

  • unhandledRejection
  • rejectionHandled
let rejected;
process.on("unhandledRejection",function(reason,promise){
  console.log(reason.message); // "Explosin"
  console.log(rejected === promise); // "Explosin"
})
rejected = Promise.reject(new Error('Explosin'))

Chaining Promises and Chained Return Values

let p1 = new Promise(function(resolve,reject){
  resolve(42)
})
p1.then(function(value){
  console.log(value)
  return value+1;
})
.then(function(value){
  console.log(value); // "43"
})

let p1 = new Promise(function(resolve,reject){
  reject(42)
})
p1.catch(function(value){
  console.log(value) // 42
  return value+1;
})
.then(function(value){
  console.log(value); // "43"
})

Returning Promises in a Promise Chain

Promise.all()

It accepts only one argument and returns a Promise. This argument is an iterable object containing multiple monitored Promises. The returned Promise will only be resolved when all Promises in the iterable object are resolved, and it will only be fulfilled when all Promises in the iterable object are fulfilled. As long as one Promise is rejected, the returned Promise will be rejected without waiting for all others to complete.

let p1 = new Promise(function(resolve,reject){
  resolve(42)
})
let p2 = new Promise(function(resolve,reject){
  reject(43)
})
let p3 = new Promise(function(resolve,reject){
  resolve(44)
})
let p4 =  Promise.all([p1,p2,p3])
p4.catch(function(value){
  console.log(Array.isArray(value)); //false
  console.log(value); // 43
})

Promise.race()

As long as one Promise resolves, there’s no need to wait for all of them to complete. Once a Promise in the array is fulfilled, the Promise.race() method will also return a specific Promise, just like the Promise.all() method.

Promise Inheritance

class MyPromise extends Promise {
  // 使用默认的构造函数

  success(resolove,reject){
    return this.then(resolove,reject)
  }
  failure(reject){
    return this.catch(reject)
  }
}
let promise = new MyPromise(function(resolve,reject){
  resolve(42)
})
promise.success(function(value){
  console.log(value) // 42
})
.failure(function(value){
  console.log(value)
})

Promise-based Asynchronous Task Execution

Refactoring the previous file reading functionality. As long as every asynchronous operation returns a Promise, this process can be greatly simplified and made usable. Using Promises as a common interface for all asynchronous code can simplify the task executor.

let fs = require("fs");

function run(taskDef){
  // 创建迭代器
  let task = taskDef()

  // 开始执行任务
  let result = task.next();

  // 递归函数遍历
  (function step(){
    // 如果有更多任务要做
    if(!result.done){
      // 用一个Promise来解决会简化问题
      let promise = Promise.resolove(result.value);
      promise.then(function(value){
        result = task.next(value);
        step()
      })
      .catch(function(error){
        result = task.throw(error);
        step();
      })
    }

  }())
}
// 定义一个可用于任务执行器的函数
function readFile(filename){
  return new Promise(function(resolove,reject){
    fs.readFile(filename,function(err,contents){
      if(err){
        reject(err);
      } else {
        resolove(contents)
      }
    })
  })
}

// 执行一个任务
run(function *(){
  let contents = yield readFile("config.json");
  doSomethingWith(contents);
  console.log("Done")
})