Promise 对象用于异步计算。一个 Promise 表示一个现在将来永不可能可用的值。

语法

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

参数

executor
executor是一个带有resolve和reject两个参数的函数 。executor 函数由Promise实现立即执行,传递resolve和reject函数(在Promise构造函数之前调用执行器甚至返回创建的对象)。resolve 和 reject 函数,当被调用时,分别解决或拒绝 promise。executor 通常会启动一些异步工作,然后,一旦完成,可以调用resolve函数来解决promise,否则在发生错误时拒绝它。
如果在executor函数中抛出一个错误,那么该promise 将被拒绝。executor的返回值被忽略。

描述

Promise 对象是一个代理对象(代理一个值),被代理的值在Promise对象创建时可能是未知的。它允许你为异步代码执行结果的成功和失败分别绑定相应的处理方法(handlers )。 这让异步方法可以像同步方法那样返回值,但是并非立即返回执行的结果,因为毕竟执行的是异步代码,因此,它会返回一个Promise对象,如前所说,它是一个代理的对象,代理了最终返回的值,可以在后期使用

一个 Promise有以下几种状态:

  • pending: 初始状态,未履行或拒绝。
  • fulfilled: 意味着操作成功完成。
  • rejected: 意味着操作失败。

pending 状态的 Promise 对象可能以 fulfilled 状态返回了一个值,也可能被某种理由(异常信息)拒绝(reject)了。当其中任一种情况出现时,Promise 对象的 then 方法绑定的处理方法handlers )就会被调用(then方法包含两个参数:onfulfilled 和 onrejected,它们都是 Function 类型。当值被填充时,调用 then 的 onfulfilled 方法,当Promise被拒绝时,调用 then 的 onrejected 方法, 所以在异步操作的完成和绑定处理方法之间不存在竞争)。

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

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

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

属性

Promise.length
长度属性,其值为 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的rejected句柄,并返回这个Promise对象。
Promise.resolve(value)
用成功值value完成一个Promise对象。如果该value为可继续的(thenable,即带有then方法),返回的Promise对象会“跟随”这个value,采用这个value的最终状态;否则的话返回值会用这个value满足(fullfil)返回的Promise对象。

Promise原型

属性

方法

示例

非常简单的例子 (就10行!)

var myFirstPromise = new Promise(function(resolve, reject){
    //当异步代码执行成功时,我们才会调用resolve(...), 当异步代码失败时就会调用reject(...)
    //在本例中,我们使用setTimeout(...)来模拟异步代码,实际编码时可能是XHR请求或是HTML5的一些API方法.
    setTimeout(function(){
        resolve("成功!"); //代码正常执行!
    }, 250);
});

myFirstPromise.then(function(successMessage){
    //successMessage的值是上面调用resolve(...)方法传入的值.
    //successMessage参数不一定非要是字符串类型,这里只是举个例子
    console.log("Yay! " + successMessage);
});

创建一个 Promise

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

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

'use strict';
var promiseCount = 0;

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

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

    // 新建一个Promise对象
    var p1 = new Promise(
        function(resolve, reject) {
            log.insertAdjacentHTML('beforeend', thisPromiseCount +
                ') Promise started (<small>Async code started</small>)<br/>');
            // 模拟异步代码
            window.setTimeout(
                function() {
                    // 填充(fulfilled))promise
                    resolve(thisPromiseCount);
                }, Math.random() * 2000 + 1000);
        }
    );

    // 通过调用then方法,我们定义了当promise被成功解析(resolved)/填充(fulfilled)时要执行的代码,
    // 而catch()方法则定义了当promise被拒绝(rejected)时要执行的代码.
    p1.then(
        // 记录被填充的值
        function(val) {
            log.insertAdjacentHTML('beforeend', val +
                ') Promise fulfilled (<small>Async code terminated</small>)<br/>');
        })
    .catch(
        // 记录被拒绝的理由(异常信息)
        function(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架构。

规范

规范 状态 备注
ECMAScript 2015 (6th Edition, ECMA-262)
Promise
Standard ECMA标准中的首次定义
ECMAScript Latest Draft (ECMA-262)
Promise
Draft  

浏览器兼容性

Feature Chrome Edge Firefox Internet Explorer Opera Safari Servo
Promise32.0(Yes)29.01No support197.12No support
Promise.all32.0(Yes)29.0No support197.1No support
Promise.prototype32.0(Yes)29.0No support197.1No support
Promise.prototype.catch32.0(Yes)29.0No support197.1No support
Promise.prototype.then32.0(Yes)29.0No support197.1No support
Promise.race32.0(Yes)29.0No support197.1No support
Promise.reject32.0(Yes)29.0No support197.1No support
Promise.resolve32.0(Yes)29.0No support197.1No support
Feature Android Chrome for Android Edge Mobile Firefox for Android IE Mobile Opera Mobile Safari Mobile
Promise4.4.432.0(Yes)291No support(Yes)8.02
Promise.all4.4.432.0(Yes)29No support(Yes)8.0
Promise.prototype4.4.432.0(Yes)29No support(Yes)8.0
Promise.prototype.catch4.4.432.0(Yes)29No support(Yes)8.0
Promise.prototype.then4.4.432.0(Yes)29No support(Yes)8.0
Promise.race4.4.432.0(Yes)29No support(Yes)8.0
Promise.reject4.4.432.0(Yes)29No support(Yes)8.0
Promise.resolve4.4.432.0(Yes)29No support(Yes)8.0

1. Constructor requires a new operator since version 37.

2. Constructor requires a new operator since version 10.

参见

文档标签和贡献者

 最后编辑者: lindaxiao-hust,