深入理解ES6 011【学习笔记】

Promise与异步编程

因为执行引擎是单线程的,所以需要跟踪即将运行的代码,那些代码被放在一个任务队列中,每当一段代码准备执行时,都会被添加到任务队列中,每当引擎中的一段代码结束执行,事件循环会执行队列中的一下个任务。

Promise相当于异步操作结果占位符,它不会去订阅一个事件,也不会传递一个回调函数给目标函数,而是让函数返回一个Promise,就像这样

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

Promise的生命周期

  • pending
  • fulfilled 成功
  • rejected 程序错误或一些其他原因

[[PromiseState]]内部属性被用来表示Promise的3种状态,这个属性不暴露在Promise对象上,所以不能以编程的方式检测Promise的状态,只有当Promise状态改变时,通过then()方法来采取特定的行为。所以Promise都有then方法,它接受两个参数,fulfilled和rejected时的两个回调函数

如果一个对象实现了上述的then方法,那这个对象我们就称之为thenable对象,所有的Promise对象都是thenable对象,但并非所有thenable对象都是Promise。

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){
  // 拒绝
})

如果向Promise.resolve()方法或Promise.reject()方法传入一个Promise,那么这个Promise会被直接返回

Nodejs环境的拒绝处理

  • 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'))

串联Promise及链式返回值

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"
})

在Promsie链返回Promise

Promise.all()

只接受一个参数并返回一个Promise,该参数是一个含有多个受监视Promise的可迭代对象,只有当可迭代对象中所有Promise都被解决后返回的Promise才会被解决,只有当可迭代对象中所有Promise都完成后返回的promise才会被完成。只要有一个reject,就不用等所有的都完成就会被reject。

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()

只要有一个resolve,不用等所有的都被完成。一旦数组中的某个Promise被完成,Promise.race()方法也会像Promise.all()方法一样返回一个特定的Promise

Promise继承

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的异步任务执行

改造之前的文件读取功能。只要每个异步操作都返回Promise,就可以极大地简化并能用化这个过程。以Promise作为通用接口用于所有异步代码可以简化任务执行器。

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")
})

主题测试文章,只做测试使用。发布者:Walker,转转请注明出处:https://joyjs.cn/archives/4337

(0)
Walker的头像Walker
上一篇 2025年3月8日 13:04
下一篇 2025年3月8日 12:52

相关推荐

  • 深入理解ES6 010【学习笔记】

    改进的数组功能 new Array()的怪异行为,当构造函数传入一个数值型的值,那么数组的length属性会被设为该值;如果传入多个值,此时无论这些值是不是数值型的,都会变为数组的元素。这个特性另人困惑,你不可能总是注意传入数据的类型,所以存在一定的风险。 Array.of() 无论传多少个参数,不存在单一数值的特例(一个参数且数值型),总是返回包含所有参数…

    个人 2025年3月8日
    37000
  • 深入理解ES6 006【学习笔记】

    Symbol和Symbol属性 第6种原始数据类型:Symbol。私有名称原本是为了让开发者们创建非字符串属性名称而设计的,但是一般的技术无法检测这些属性的私有名称 创建Symbol let firstName = Symbol(); let person = {} person[firstName] = "Nicholas"; cons…

    个人 2025年3月8日
    48900
  • 测试专题

    个人 2025年2月7日
    40500
  • Go工程师体系课 protoc-gen-validate【学习笔记】

    protoc-gen-validate 简介与使用指南 ✅ 什么是 protoc-gen-validate protoc-gen-validate(简称 PGV)是一个 Protocol Buffers 插件,用于在生成的 Go 代码中添加结构体字段的验证逻辑。 它通过在 .proto 文件中添加 validate 规则,自动为每个字段生成验证代码,避免你手…

    个人 2025年4月27日
    20900
  • 深入理解ES6 002【学习笔记】

    字符串和正则表达式 字符串和正则表达式 Javascript字符串一直基于16位字符编码(UTF-16)进行构建。每16位的序列是一个编码单元(code unit),代表一个字符。length、charAt()等字符串属性和方法都基于这个编码单元构造的。Unicode的目标是为世界上每一个字符提供全球唯一的标识符。如果我们把字符长度限制在16位,码位数量将不…

    个人 2025年3月8日
    52900

联系我们

400-800-8888

在线咨询: QQ交谈

邮件:admin@example.com

工作时间:周一至周五,9:30-18:30,节假日休息

关注微信
欢迎🌹 Coding never stops, keep learning! 💡💻 光临🌹