ES6躬行记(23)——Promise的静态方法和应用

简介:   Promise有四个静态方法,分别是resolve()、reject()、all()和race(),本节将着重分析这几个方法的功能和特点。

一、静态方法


  Promise有四个静态方法,分别是resolve()、reject()、all()和race(),本节将着重分析这几个方法的功能和特点。

1)Promise.resolve()

  此方法有一个可选的参数,参数的类型会影响它的返回值,具体可分为三种情况(如下所列),其中有两种情况会创建一个新的已处理的Promise实例,还有一种情况会返回这个参数。

(1)当参数为空或非thenable时,返回一个新的状态为fulfilled的Promise。

(2)当参数为thenable时,返回一个新的Promise,而它的状态由自身的then()方法控制,具体细节已在之前的thenable一节做过说明。

(3)当参数为Promise时,将不做修改,直接返回这个Promise。

  下面用一个例子演示这三种情况,注意观察Promise的then()方法的第一个回调函数中接收到的决议结果。


let tha = {
  then(resolve, reject) {
    resolve("thenable");
  }
};
//参数为空
Promise.resolve().then(function(value) {
  console.log(value);    //undefined
});
//参数为非thenable
Promise.resolve("string").then(function(value) {
  console.log(value);    //"string"
});
//参数为thenable
Promise.resolve(tha).then(function(value) {
  console.log(value);    //"thenable"
});
//参数为Promise
Promise.resolve(new Promise(function(resolve) {
  resolve("Promise");
})).then(function(value) {
  console.log(value);    //"Promise"
});


2)Promise.reject()

  此方法能接收一个参数,表示拒绝理由,它的返回值是一个新的已拒绝的Promise实例。与Promise.resolve()不同,Promise.reject()中所有类型的参数都会原封不动的传递给后续的已拒绝的回调函数,如下代码所示。


Promise.reject("rejected").catch(function (reason) {
  console.log(reason);          //"rejected"
});
var p = Promise.resolve();
Promise.reject(p).catch(function (reason) {
  reason === p;                 //true
});


  第一次调用Promise.reject()的参数是一个字符串,第二次的参数是一个Promise,catch()方法中的回调函数接收到的正是这两个参数。

3)Promise.all()

  此方法和接下来要讲解的Promise.race()都可用来监控多个Promise,当它们的状态发生变化时,这两个方法会给出不同的处理方式。

  Promise.all()能接收一个可迭代对象,其中可迭代对象中的成员必须是Promise,如果是字符串、thenable等非Promise的值,那么会自动调用Promise.resolve()转换成Promise。Promise.all()的返回值是一个新的Promise实例,当参数中的成员为空时,其状态为fulfilled;而当参数不为空时,其状态由可迭代对象中的成员决定,具体分为两种情况。

  (1)当可迭代对象中的所有成员都是已完成的Promise时,新的Promise的状态为fulfilled。而各个成员的决议结果会组成一个数组,传递给后续的已完成的回调函数,如下所示。


var p1 = Promise.resolve(200),
  p2 = "fulfilled";
Promise.all([p1, p2]).then(function (value) {
  console.log(value);          //[200, "fulfilled"]
});

  (2)当可迭代对象中的成员有一个是已拒绝的Promise时,新的Promise的状态为rejected。并且只会处理到这个已拒绝的成员,接下来的成员都会被忽略,其决议结果会传递给后续的已拒绝的回调函数,如下所示。

var p1 = Promise.reject("error"),
  p2 = "fulfilled";
Promise.all([p1, p2]).catch(function (reason) {
  console.log(reason);         //"error"
});

4)Promise.race()

  此方法和Promise.all()有很多相似的地方,如下所列。

(1)能接收一个可迭代对象。

(2)成员必须是Promise,对于非Promise的值要用Promise.resolve()做转换。

(3)返回值是一个新的Promise实例。

  新的Promise实例的状态也与方法的参数有关,当参数的成员为空时,其状态为pending;当参数不为空时,其状态是最先被处理的成员的状态,并且此成员的决议结果会传递给后续相应的回调函数,如下代码所示。


var p1 = new Promise(function(resolve) {
  setTimeout(() => {
    resolve("fulfilled");
  }, 200);
});
var p2 = new Promise(function(resolve, reject) {
  setTimeout(() => {
    reject("rejected");
  }, 100);
});
Promise.race([p1, p2]).catch(function (reason) {
  console.log(reason);      //"rejected"
});


  在p1和p2的执行器中都有一个定时器。由于后者的定时器会先执行,因此通过调用Promise.race([p1, p2])得到的Promise实例,其状态和p2的相同,而p2的决议结果会作为拒绝理由被catch()方法中的回调函数接收。

  根据前面的分析可以得出,Promise.all()能处理一个或多个受监控的Promise,而Promise.race()只能处理其中的一个。


二、应用


1)Promise和生成器

  用Promise和生成器实现一个运行器,可以取代冗长的Promise链,以一种更直观的方式控制异步,类似于下面这样。

function load() {
  return new Promise(function(resolve, reject) {
    resolve("success");
  });
}
run(function* ()    {
  var result = yield load();
  console.log(result);        //"success"
});


  在load()函数内部,执行的是异步操作,由于处在run运行器中,因此它的决议结果可通过赋值语句直接给到result。这种工作模式完全颠覆了过去用回调函数接收异步操作结果的模式。为此,ES8规范特地引入了两个关键字:async和await,支持这种便捷的工作模式,下面改写上一个示例,用新语法实现相同的功能。

(async function() {
  var result = await load();
  console.log(result);        //"success"
})();

  关于run运行器的工作原理和ES8的新语法,限于篇幅原因,此处不再展开说明。

2)与传统异步操作的组合

  以往需要用回调函数接收异步处理结果的操作,现在都能改成Promise的模式。以图像加载为例,当图像载入成功时,会触发load事件;而当失败时,会触发error事件。如果后续又有异步操作,那么就只能在这两个事件中处理,但这么一来,就会形成难以控制的回调金字塔。而改用Promise后,就能链式的处理后续的操作,如下所示。


function preImg(src) {
  return new Promise(function (resolve, reject) {
    var img = new Image();
    img.src = src;
    img.onload = function(){
      resolve(this);
    };
    img.onerror = function(){
      reject(this);
    };
  });
};
preImg("img/page.png").then(function(value) {
  console.log(value);
});
相关文章
|
1月前
|
前端开发 小程序 JavaScript
es6读书笔记(五)Promise
es6读书笔记(五)Promise
|
4月前
|
前端开发 JavaScript 测试技术
ES6:什么是Promise
ES6:什么是Promise
|
4月前
|
前端开发 JavaScript
ES6中什么是Promise?
ES6中什么是Promise?
|
4月前
|
JSON 前端开发 JavaScript
ES6类的使用和定义.Json.Promise对象的使用
ES6类的使用和定义.Json.Promise对象的使用
25 0
|
2月前
|
前端开发 JavaScript
JavaScript中的异步编程及Promise的应用
在前端开发中,异步编程是常见的需求,而Promise作为一种解决异步操作的技术,具有很高的应用价值。本文将介绍JavaScript中的异步编程原理,并结合实际案例详细讲解Promise的使用方法及其在前端开发中的应用。
12 2
|
2月前
|
前端开发 JavaScript
JavaScript 中的异步编程:Promise 和 Async/Await 的实现与应用
在Web开发中,JavaScript异步编程是一个不可忽视的重要话题。本文将深入探讨JavaScript中Promise和Async/Await的实现原理与应用场景,通过实例代码带您了解如何优雅地处理异步操作,提升代码的可读性和可维护性。
|
3月前
|
前端开发 JavaScript
JavaScript中的异步编程及Promise应用
在现代Web开发中,JavaScript的异步编程已经成为不可或缺的一部分。本文将介绍JavaScript中的异步编程概念,探讨回调地狱问题,并详细介绍Promise作为一种更优雅的解决方案。通过示例代码和实际场景应用,帮助读者更好地理解和应用Promise来处理异步操作。
|
3月前
|
前端开发 JavaScript API
JavaScript中的异步编程及Promise应用
在现代Web开发中,JavaScript的异步编程已经成为了一个重要的话题。本文将介绍JavaScript中的异步编程模式,以及通过Promise对象来简化异步操作的方法。通过深入理解并掌握JavaScript中的异步编程,可以提高代码的可读性和可维护性,从而更好地应对复杂的业务逻辑。
13 2
|
3月前
|
资源调度 前端开发 JavaScript
vue - ES6模块化、promise、webpack打包(所在在学的朋友们先看这篇,看了不吃亏)...
vue - ES6模块化、promise、webpack打包(所在在学的朋友们先看这篇,看了不吃亏)...
|
4月前
|
前端开发 JavaScript
JavaScript开发中ES6+新特性:如何使用Promise来处理异步操作?
JavaScript开发中ES6+新特性:如何使用Promise来处理异步操作?
30 1