ES6中的Promise深入解析

逃离我推掉我的手 2022-05-22 01:24 300阅读 0赞

promise主要是为了解决回调带来的疯狂行为, Promise 风暴已经开始席卷JavaScript 世 界。

实际上,绝大多数 JavaScript/DOM 平台新增的异步 API 都是基于 Promise 构建的。


一. 异步编程的背景

JavaScript 的引擎建立在单线程事件轮询(single-threaded event loop)概念之上。

单线程意味着一段时间内只能执行一段代码,与 Java 和 C++ 这些允许多段代码同时执行的多线程语言形成了鲜明对比。

JavaScript 引擎在相同的时间内只能执行一段代码.

当代码由 JavaScript 引擎执行完毕后,引擎通过 event loop 找到并执行队列中的下一个任务。

event loop 是 JavaScript 引擎内部的线程用来监控代码的执行情况和管理任务队列。

需要牢记的是既然它是个队列,那么任务就会由开始到最后的顺序依次执行。


二. Promise出来之前的两种异步编程方式

  1. 事件模型

不够灵活.

  1. 回调模式

回调地狱


三. promise基础

一个 Promise 就是一个代表了异步操作最终完成或者失败的对象。

可以把Promise理解成对将来的一个”承诺”. 这个承诺不管将来如何一定会有一个结果:要么兑现承诺, 要么不兑现. 不管结果是什么, 都会对被承诺者一个交代.

我们通常有两种方式来获取到一个Promise对象:

  1. 使用Promise构造函数来创建Promise对象
  2. 调用其他的一些api返回一个Promise对象.(其实是这些api内部创建并返回了Promise对象)

我们先用第一种方式来深入的理解下promise.


promise 的生命周期(The Promise Lifecycle)

  1. 每个 promise 的生命周期一开始都会处于短暂的挂起(pending)状态,表示异步操作仍未完成,即挂起的 promise 被认定是未定的(unsettled)。
  2. 一旦异步操作完成,promise 就被认为是已定(settled)的并处于以下的两种状态之一:

    • fulfilled(resolved): promise 的异步操作已完成。
    • rejected: promise 的异步操作未完成,原因可能是发生了错误或其它理由。

创建Promise对象并添加异步任务

使用构造函数Promise来创建Promise对象.

需要接收一个执行函数(executor), 这个函数内包含了初始化Promise的一些代码.
该执行函数接收 resolve 和 reject 两个参数(其实是两个函数)。
- resolve 函数会在执行函数成功运行后发出信号表示该 promise 已经可用,
- reject 函数代表改执行函数运行失败。

  1. /* 对setTimeout 用promise作封装 创建出来一个未定的promise 注意: 1. 创建Promise对象的时候, 执行函数的内的代码会立即执行. 2. 当 resolve() 和 reject() 在执行函数内部被调用后, 为了处理这个 promise,一个任务会被放置到任务队列中。 该种行为被称为任务调度(job scheduling) */
  2. var count = 1;
  3. let promise = new Promise(function (resolve, reject){
  4. if(count == 1){
  5. resolve("成功了");
  6. }else{
  7. reject("失败了");
  8. }
  9. });
  10. /*添加异步任务 * then需要两个函数: * 函数1:异步操作成功之后的回调函数 * 函数2:异步操作失败之后的回调函数 * */
  11. promise.then(function (value){
  12. console.log(value);
  13. }, function (value){
  14. console.log(value)
  15. });

注意:

  • Promise的意思是承诺,保证. 他带来了哪些保证呢?
  • 在JavaScript事件队列的当前运行完成之前,回调函数永远不会被调用。
  • 通过 .then 形式添加的回调函数,甚至都在异步操作完成之后才被添加的函数,都会被调用
  • 通过多次调用 .then,可以添加多个回调函数,它们会按照插入顺序并且独立运行。

四. Promise链式调用

一个常见的需求就是连续执行两个或者多个异步操作,这种情况下,每一个后来的操作都在前面的操作执行成功之后,带着上一步操作所返回的结果开始执行。

我们可以通过创造一个promise chain来完成这种需求。

这也是Promise的神奇之处.

是因为: 每次调用then方法会返回一个全新的Promise对象:

  1. promise.then(function (value){
  2. console.log(value);
  3. }, function (value){
  4. console.log(value)
  5. }).then(function (){
  6. console.log("哈哈哈")
  7. })

在链中传递数据

  1. promise.then(function (value){
  2. console.log(value);
  3. return value + "1"; // 给后面的异步任务传递数据
  4. }, function (value){
  5. console.log(value)
  6. }).then(function (value){
  7. console.log("哈哈哈", value)
  8. })

五. 捕获错误

通过前面的学习我们已经知道, then的第二个参数是用来处理错误.

其实我们可以省略这个参数不处理错误.

省略第二个参数:

  1. promise.then(function (value){
  2. console.log(value);
  3. return value + "1";
  4. })

也可以使用catch来专门来处理错误:

  1. promise.then(function (value){
  2. console.log(value);
  3. }).catch(function (value){
  4. console.log(value);
  5. })
  6. // 与下面完全等价:
  7. promise.then(function (value){
  8. console.log(value);
  9. }, function (value){
  10. console.log(value);
  11. console.log(a);
  12. })

注意:

  • catch也会返回一个新的promise对象

六. 关于then返回的promise

好好体会

then方法总是返回一个新的Promise,而它的行为与then中的回调函数的返回值有关:

  • 如果then中的回调函数返回一个值,那么then返回的Promise将会成为接受状态,并且将返回的值作为接受状态的回调函数的参数值。
  • 如果then中的回调函数抛出一个错误,那么then返回的Promise将会成为拒绝状态,并且将抛出的错误作为拒绝状态的回调函数的参数值。
  • 如果 then 中的回调函数返回的是一个 promise A, 那么then返回的promise B的状态始终会与 promise A 保持一致. 并且回调函数的参数值也始终相同.
  • promise A的回调函数的参数也始终与 promise B的回调函数的参数保持一致.

使用promise封装ajax

发表评论

表情:
评论列表 (有 0 条评论,300人围观)

还没有评论,来说两句吧...

相关阅读

    相关 ES6Promise用法

    一.Promise是什么 promise是一个对象,对象和函数的区别就是对象可以保存状态,函数不可以(闭包除外) 并未剥夺函数return的能力,因此无需层层传递ca

    相关 ES6-Promise

    Promise what? 在我看来Promise就相当于一个承诺容器,将所要执行的事件存贮在promise容器中。 Promise在ES6中被统一规范,由浏览

    相关 ES6promise法则

    一,promise用来解决什么问题的 > Promise > 为异步编程提供统一的解决方案,比传统的回调和事件更加合理有效。多重嵌套的回调函数,代码是横向发展,不是纵

    相关 ES6 Promise 使用

      Promise 是什么?         Promise 是一个对象,它用于异步计算。它可以将异步操作队列化,按照期望的顺序执行,并返回符合预期的结果。它是异步编程