# 剑指前端(前端入门笔记系列)——Promise

一、简介

  Promise 是异步编程的一种解决方案:从语法上讲,promise是一个对象,从它可以获取异步操作的消息;从本意上讲,它是承诺,承诺它过一段时间会给你一个结果。promise有三种状态:pending(等待态),fulfiled(成功态),rejected(失败态);状态一旦改变,就不会再变。创造promise实例后,它会立即执行。

1.1 问题场景

  为了解决类似于回调地狱之类的问题,回调地狱是指回调函数,一个嵌套着一个。到最后造成了可阅读性差,可阅读性差就代表代码的可维护性和可迭代性差,最后还有一个就是可扩展性差。也不符合设计模式中的单一职责原则和开闭原则。

例如:我只有得到了a,才能得到b,进而得到c…

function fn1(a) {
	console.log("fn1执行了!")
    a();
}
function fn2(b) {
	console.log("fn2执行了!")
    b();
};
function fn3(c) {
	console.log("fn3执行了!")
    c();
};
function fn4() {
	console.log("fn4执行了!")
};
fn1(() => {
  fn2(() => {
    fn3(() => {
      fn4()
    })
  })
});

fn1执行了
fn2执行了
fn3执行了
fn4执行了

  这样写代码虽然视觉效果还不错,还用代码围出了一个三角形,但是对于编程来说有害而无利,可是这种需求还很多,所以不得不解决,就这样,Promise作为其中的一种解决手段问世了。

1.2 优化方案

  我们先使用Promise来优化之前的案例,虽然可能代码不会减少,甚至更多,但是却大大增强了其可读性和可维护性(其中用到的语法会在后面介绍):

function fn1() {
	return new Promise(resolve => {
		console.log("fn1执行了")
		resolve()
	})
}
function fn2() {
	console.log("fn2执行了")
}
function fn3() {
	console.log("fn3执行了")
}
function fn4() {
	console.log("fn4执行了")
}

fn1()
.then(fn2)
.then(fn3)
.then(fn4)

fn1执行了
fn2执行了
fn3执行了
fn4执行了

1.3 作用

promise主要是为了解决js中多个异步回调难以维护和控制的问题.

  1. 主要用于异步计算
  2. 可以将异步操作队列化,按照期望的顺序执行,返回符合预期的结果
  3. 可以在对象之间传递和操作promise,帮助我们处理队列

1.4 组成

在这里插入图片描述

二、详解

2.1 开启方式

  首先我们来看一下Promise的使用语法:

new Promise(
    /*excutor*/
    function(resolve,reject){}
);

  在实例化Promise时需要传入一个函数excutor作为参数,并且在Promise构造函数执行时同步执行,先看一个简单的实例:

var p = new Promise(function(resolve,reject){
     var timer = setTimeout(function(){
         console.log('执行操作1');
     },1000);
 });

  我们可以看到1s后在控制台输出相应的结果,这就说明在实例化过程中,作为参数的excutor函数也会执行。从上面的实例中我们看到,excutor函数还有两个参数resolve和reject,其实这两个参数也是函数,在excutor执行时被调用,之后会具体来描述resolve和reject的用法。

2.2 核心方法

  • then()——promise对象状态改变了才会执行的函数,否则一直处于“等待”状态’
      then方法里面有两个参数onfulfilled(Promise为fulfilled状态时执行) 和onrejected(Promise为rejected状态时执行),这两个参数都是以函数为参数的回调函数(若传入非函数,则会忽略当前then方法)。回调函数中会把上一个then中返回的值当做参数值供当前then方法调用。then方法执行完毕后需要返回一个新的值给下一个then调用(没有返回值默认使用undefined)。每个then只可能使用前一个then的返回值。
  • resolve()——异步操作执行成功后的回调函数
      在excutor函数中调用resolve方法时,会让Promise的状态变成fulfilled,即操作成功状态,这时会执行onfulfilled函数(then方法里的第一个参数)
var p = new Promise(function (resolve, reject) {
    console.log('执行操作1');
    resolve('这是数据1');
});
p.then(function (data) {
    console.log(data);
    console.log('这是成功操作');
});

  运行结果:

执行操作1
这是数据1
这是成功操作
  • reject()——异步操作执行失败后的回调函数
      在excutor函数中调用resolve方法时,会让Promise的状态就变成rejected,即操作失败状态,这时会执行onrejected函数(then方法里的第一个参数)
var p = new Promise(function (resolve, reject) {
  var flag = false;
  if(flag){
    resolve('这是数据2');
  }else{
    reject('这是数据2');
  }
});
p.then(function(data){//状态为fulfilled时执行
    console.log(data);
    console.log('这是成功操作');
},function(reason){ //状态为rejected时执行
    console.log(reason);
    console.log('这是失败的操作');
});

运行结果

这是数据2
这是失败的操作
  • catch()——异步操作执行失败后执行的函数
      其实跟then方法中的第二个参数一样,就是在Promise状态为rejected时执行,then()方法捕捉到Promise的状态为rejected,就执行catch方法里面的操作,下面用catch()方法改写上面reject用法里面的例子,如下所示:

var p = new Promise(function (resolve, reject) {
  var flag = false;
  if(flag){
    resolve('这是数据2');
  }else{
    reject('这是数据2');
  }
});
p.then(function(data){//状态为fulfilled时执行
  console.log(data);
  console.log('这是成功操作');
}).catch(function(reason){//状态为rejected时执行
  console.log(reason);
  console.log('这是失败的操作');
});

  执行结果和上面reject用法的例子一样。所以说,当Promise状态为rejected时有两种方式处理,一种是在then方法中加入第二个参数,另一种是在then()函数后面连缀一个catch方法。

发布了24 篇原创文章 · 获赞 43 · 访问量 9791

猜你喜欢

转载自blog.csdn.net/weixin_37844113/article/details/103600200