非常教程

JavaScript参考手册

Promise

Promise

Promise 对象用于表示一个异步操作的最终状态(完成或失败),以及其返回的值。

本条目为Promise构造函数。想要了解promises,请首先阅读使用 promises。构造函数主要是用来包装还未支持promises的函数。

语法

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

参数说明

executor:带有 resolve 和 reject 两个参数的函数 。Promise 构造函数执行时立即调用executor函数, resolve 和 reject 两个函数作为参数传递给executor(executor 函数在 Promise 构造函数返回新建对象前被调用)。resolve 和 reject 函数被调用时,分别将 promise 的状态改为 fulfilled(完成)或 rejected(失败)。executor 内部通常会执行一些异步操作,一旦完成,可以调用 resolve 函数来将 promise 状态改成 fulfilled,或者在发生错误时将它的状态改为 rejected

如果在executor函数中抛出一个错误,那么该promise 状态为rejected。executor函数的返回值被忽略。

描述

Promise 对象是一个代理对象(代理一个值),被代理的值在Promise对象创建时可能是未知的。它允许你为异步操作的成功和失败分别绑定相应的处理方法(handlers)。 这让异步方法可以像同步方法那样返回值,但并不是立即返回最终执行结果,而是一个能代表未来出现的结果的promise对象

一个 Promise有以下几种状态:

  • pending: 初始状态,既不是成功,也不是失败状态。

  • fulfilled: 意味着操作成功完成。

  • rejected: 意味着操作失败。

pending 状态的 Promise 对象可能触发fulfilled 状态并传递一个值给相应的状态处理方法,也可能触发失败状态(rejected)并传递失败信息。当其中任一种情况出现时,Promise 对象的then方法绑定的处理方法(handlers )就会被调用(then方法包含两个参数:onfulfilled 和 onrejected,它们都是 Function 类型。当Promise状态为fulfilled时,调用 then 的 onfulfilled 方法,当Promise状态为rejected时,调用 then 的 onrejected 方法, 所以在异步操作的完成和绑定处理方法之间不存在竞争)。

因为 Promise.prototype.then和  Promise.prototype.catch方法返回promise 对象, 所以它们可以被链式调用。

不要和惰性求值混淆: 有一些语言中有惰性求值和延时计算的特性,它们也被称为“promises”,例如Scheme. Javascript中的promise代表一种已经发生的状态, 而且可以通过回调方法链在一起。 如果你想要的是表达式的延时计算,考虑无参数的"箭头方法":  f = () =>表达式创建惰性求值的表达式使用f()求值。

注意: 如果一个promise对象处在fulfilled或rejected状态而不是pending状态,那么它也可以被称为settled状态。你可能也会听到一个术语resolved ,它表示promise对象处于fulfilled状态。关于promise的术语, Domenic Denicola 的 States and fates 有更多详情可供参考。

属性

Promise.lengthlength属性,其值总是为 1 (构造器参数的数目).Promise.prototype表示 Promise 构造器的原型.

方法

Promise.all(iterable)这个方法返回一个新的promise对象,该promise对象在iterable参数对象里所有的promise对象都成功的时候才会触发成功,一旦有任何一个iterable里面的promise对象失败则立即触发该promise对象的失败。这个新的promise对象在触发成功状态以后,会把一个包含iterable里所有promise返回值的数组作为成功回调的返回值,顺序跟iterable的顺序保持一致;如果这个新的promise对象触发了失败状态,它会把iterable里第一个触发失败的promise对象的错误信息作为它的失败错误信息。Promise.all方法常被用于处理多个promise对象的状态集合。(可以参考jQuery.when方法---译者注)Promise.race(iterable)当iterable参数里的任意一个子promise被成功或失败后,父promise马上也会用子promise的成功返回值或失败详情作为参数调用父promise绑定的相应句柄,并返回该promise对象。Promise.reject(reason)返回一个状态为失败的Promise对象,并将给定的失败信息传递给对应的处理方法Promise.resolve(value)返回一个状态由给定value决定的Promise对象。如果该值是一个Promise对象,则直接返回该对象;如果该值是thenable(即,带有then方法的对象),返回的Promise对象的最终状态由then方法执行决定;否则的话(该value为空,基本类型或者不带then方法的对象),返回的Promise对象状态为fulfilled,并且将该value传递给对应的then方法。通常而言,如果你不知道一个值是否是Promise对象,使用Promise.resolve(value) 来返回一个Promise对象,这样就能将该value以Promise对象形式使用。

Promise 原型

属性

Promise.prototype.constructor返回被创建的实例函数.  默认为 Promise函数.

方法

Promise.prototype.catch(onRejected)添加一个拒绝(rejection) 回调到当前 promise, 返回一个新的promise。当这个回调函数被调用,新 promise 将以它的返回值来resolve,否则如果当前promise 进入fulfilled状态,则以当前promise的完成结果作为新promise的完成结果.Promise.prototype.then(onFulfilled, onRejected)添加解决(fulfillment)和拒绝(rejection)回调到当前 promise, 返回一个新的 promise, 将以回调的返回值来resolve.

创建Promise

Promise 对象是由关键字new及其构造函数来创建的。该构造函数会?把一个叫做“处理器函数”(executor function)的函数作为它的参数。这个“处理器函数”接受两个函数——resolve 和reject ——作为其参数。当异步任务顺利完成且返回结果值时,会调用resolve 函数;而当异步任务失败且返回失败原因(通常是一个错误对象)时,会调用reject 函数。

const myFirstPromise = new Promise((resolve, reject) => {
  // do something asynchronous which eventually calls either:
  //
  //   resolve(someValue); // fulfilled
  // or
  //   reject("failure reason"); // rejected
});

想要某个函数拥有promise功能,只需让其返回一个promise即可。

function myAsyncFunction(url) {
  return new Promise((resolve, reject) => {
    const xhr = new XMLHttpRequest();
    xhr.open("GET", url);
    xhr.onload = () => resolve(xhr.responseText);
    xhr.onerror = () => reject(xhr.statusText);
    xhr.send();
  });
};

示例

非常简单的例子

let myFirstPromise = new Promise((resolve, reject) => {
  // We call resolve(...) when what we were doing asynchronously was successful, and reject(...) when it failed.
  // In this example, we use setTimeout(...) to simulate async code. 
  // In reality, you will probably be using something like XHR or an HTML5 API.
  setTimeout(function(){
    resolve("Success!"); // Yay! Everything went well!
  }, 250);
});

myFirstPromise.then((successMessage) => {
  // successMessage is whatever we passed in the resolve(...) function above.
  // It doesn't have to be a string, but if it is only a succeed message, it probably will be.
  console.log("Yay! " + successMessage);
});

高级一点的例子

本例展示了 Promise 的一些机制。 testPromise() 方法在每次点击 <button>按钮时被调用,该方法会创建一个promise 对象,使用 window.setTimeout()让Promise等待 1-3 秒不等的时间来填充数据(通过Math.random()方法)。

Promise 的值的填充过程都被日志记录(logged)下来,这些日志信息展示了方法中的同步代码和异步代码是如何通过Promise完成解耦的。

'use strict';
var promiseCount = 0;

function testPromise() {
    let thisPromiseCount = ++promiseCount;

    let log = document.getElementById('log');
    log.insertAdjacentHTML('beforeend', thisPromiseCount +
        ') Started (<small>Sync code started</small>)<br/>');

    // We make a new promise: we promise a numeric count of this promise, starting from 1 (after waiting 3s)
    let p1 = new Promise(
        // The resolver function is called with the ability to resolve or
        // reject the promise
       (resolve, reject) => {
            log.insertAdjacentHTML('beforeend', thisPromiseCount +
                ') Promise started (<small>Async code started</small>)<br/>');
            // This is only an example to create asynchronism
            window.setTimeout(
                function() {
                    // We fulfill the promise !
                    resolve(thisPromiseCount);
                }, Math.random() * 2000 + 1000);
        }
    );

    // We define what to do when the promise is resolved/rejected with the then() call,
    // and the catch() method defines what to do if the promise is rejected.
    p1.then(
        // Log the fulfillment value
        function(val) {
            log.insertAdjacentHTML('beforeend', val +
                ') Promise fulfilled (<small>Async code terminated</small>)<br/>');
        })
    .catch(
        // Log the rejection reason
       (reason) => {
            console.log('Handle rejected promise ('+reason+') here.');
        });

    log.insertAdjacentHTML('beforeend', thisPromiseCount +
        ') Promise made (<small>Sync code terminated</small>)<br/>');
}

点击下面的按钮可以看到示例代码运行的效果,前提是你的浏览器支持Promise。快速点击按钮多次你会观察到Promises填充值的过程。

使用 XHR 加载图像

另一个用了Promise和XMLHttpRequest加载一个图像的例子可在MDN GitHub promise-test 中找到。 你也可以看这个实例。每一步都有注释可以让你详细的了解Promise和XHR架构。

规范

Specification

Status

Comment

ECMAScript 2015 (6th Edition, ECMA-262)The definition of 'Promise' in that specification.

Standard

Initial definition in an ECMA standard.

ECMAScript Latest Draft (ECMA-262)The definition of 'Promise' in that specification.

Living Standard

浏览器兼容性

Feature

Chrome

Edge

Firefox

Internet Explorer

Opera

Safari

Basic Support

32.0

(Yes)

29.01

No

19

7.13

Feature

Android

Chrome for Android

Edge mobile

Firefox for Android

IE mobile

Opera Android

iOS Safari

Basic Support

4.4.4

32.0

(Yes)

291

No

(Yes)

8.03

Promise
Promise.all 详细
promise.catch 详细
Promise.prototype 详细
Promise.race 详细
Promise.reject 详细
Promise.resolve 详细
promise.then 详细
JavaScript

JavaScript 是一种高级编程语言,通过解释执行,是一门动态类型,面向对象(基于原型)的解释型语言。它已经由ECMA(欧洲电脑制造商协会)通过 ECMAScript 实现语言的标准化。它被世界上的绝大多数网站所使用,也被世界主流浏览器( Chrome、IE、FireFox、Safari、Opera )支持。JavaScript 是一门基于原型、函数先行的语言,是一门多范式的语言,它支持面向对象编程,命令式编程,以及函数式编程。它提供语法来操控文本、数组、日期以及正则表达式等,不支持 I/O,比如网络