学习ES6新增对象Promise时的问题与理解(一)


前言

  笔者最近在学习ES6新增对象Promise时遇到了一些问题,在此对我遇到的一些问题做一些整理与总结。本文主要针对本人认为的难点进行叙述总结,一些基础的内容在此不再赘述。
  本文主要参考了MDN参考文档和《JavaScript高级程序设计(第四版)》以及阮一峰大佬的《ES6标准入门》


一、对Promise的初步认识

  首先,Promise的出现是为了解决回调函数等传统异步编程方法存在的一些弊端,如著名的“回调地狱”等,也就是说Promise的主要特性和方法都是为了便于异步编程而设计的。

  然后,我们要对Promise有个宏观上的理解,到底是个什么东西。
  从语法上来说,Promise本质上是一个内置对象类型,该对象有pending, resolved(fulfilled), rejected三种内置状态,状态不受外界影响且只能改变一次。
  抽象来说,Promise可以看作一个容器,一般用来保存异步操作的结果,我们可以通过Promise获取到该异步操作的相关信息。

二、Promise构造函数

  类似于内置的String对象等,Promise也可作为构造函数,很多书和教程都是上来直接介绍Promise构造函数和then,很容易把人搞晕。个人觉得讲的最经典,也是个人觉得最好的是阮一峰大大的这段:

  Promise构造函数接受一个函数作为参数,该函数的两个参数分别是resolve和reject。它们是两个函数,由 JavaScript引擎提供,不用自己部署。
  resolve函数的作用是,将Promise对象的状态从“未完成”变为“成功”(即从 pending 变为resolved),在异步操作成功时调用,并将异步操作的结果,作为参数传递出去;
  reject函数的作用是,将Promise对象的状态从“未完成”变为“失败”(即从pending 变为 rejected),在异步操作失败时调用,并将异步操作报出的错误,作为参数传递出去。
———阮一峰《ES6标准入门》

代码表示也就是下面这样:

const promise = new Promise(function(resolve, reject) {
  // ... some code

  if (/* 异步操作成功 */){
    resolve(value);
  } else {
    reject(error);
  }
});

1. 改变状态

  再进一步理解就是Promise构造函数接收一个执行函数(executor)作为参数,执行函数有两个函数参数resolve和reject。
  这个执行函数按理说应该是个异步函数,里面有一个异步操作。根据异步操作的成功与否来调用这两个参数函数,使Promise对象的状态落定(settled),这也是唯一的改变其状态的方法,且只会改变一次。
  从这里我们可以看出:

  1. 这两个js自带的参数函数的作用之一: 改变这个Promise对象的状态。
  2. Promise对象的优点之一: 可以确定何时异步函数执行完及其是否操作成功。

2. 解决值与拒绝理由

  改变状态这一点还是很好理解的,但我们细看阮一峰大大的这段话,我们不难发现,Promise构造函数的作用还不止于此。resolve和reject这俩函数还能把异步操作的结果或报出的错误,作为参数传递出去。

  这里的操作结果也称解决值(value),操作报出的错误也称拒绝理由(reason)(拒绝理由一般都是Error类型,也可以是其他类型,未必是错误)
  resolve和reject执行时的首个参数就是他们要传递的value和reason,

resolve(value);
reject(reson);

在执行的一瞬间,Promise状态落定,且获得该参数。这也就是我们开头说它像一个容器的原因,它可以包装一个异步操作所要传递的value或reason。

function asyncWorking() {
    //函数返回一个Promise对象
    return new Promise((resolve,reject)=>{
        //2秒后执行resolve函数,参数为字符串‘succeed’
        setTimeout(resolve,2000,'succeed');
    });
}
//1秒后打印Promise对象
setTimeout(console.log,1000,asyncWorking());

//3秒后打印Promise对象
setTimeout(console.log,3000,asyncWorking());

结果如下:
执行结果

  这里有一个注意点:我在代码中是写了一个方法,把Promise对象作为返回值返回。而如果你直接new一个Promise对象,那么执行函数会直接同步执行。
  也就是说,当程序执行到你的构造函数那一行时,它直接开始执行你的执行函数,但是对于你执行函数中的异步操作依旧是正常异步执行。所以可以采用这种工厂模式来控制执行函数何时执行。

console.log(1);
let p = new Promise((resolve, reject) => {
    console.log(2);
    setTimeout(console.log, 2000, 4);
});
console.log(3);

结果如下,这里建议最好先了解一下js的异步机制,然后再学习Promise.
在这里插入图片描述


  当然这个value和reason是可选的,默认为undefined,如果没有显式参数,就把undefined传给这个Promise对象。
执行结果

由此,我们又可以又可以看出:

  1.这两个函数的作用之二:将构造函数里的异步操作的某些重要值或被拒绝的错误返回给Promise对象。
  2.Promise对象的优点之二:能保存一些有用的信息,也即value和reason。

三、下期预告

  在自学过程中,我看到很多文章包括博客都直接讲then,catch,但不少都讲的很浮于表面,只说了些常见用法,但是很少有讲到then和catch的具体实现细节,Promise作为js中实现异步的重要工具,我觉得非常有必要了解一些实现细节。我将在下一篇文章中重点讲述一下《Promise的一些常用原型方法及其实现细节》。


ps:
  • 本文中多数名词都是参照《JavaScript高级程序设计(第四版)》中的翻译,多数都已给出英文原词。
  • 新人作者,欢迎批评指正,也欢迎一起交流学习。
  • 3
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值