JavaScript的期约(Promise)

期约(Promise)

期约的状态代表期约是否完成,有三种状态:

  1. 待定(pending): 表示尚未开始或者正在执行中。

  2. 兑现(fulfilled,有时候也称为“解决”,resolved): 表示已经成功完成。

  3. 拒绝(rejected): 则表示没有成功完成,也就是已经失败。

在待定状态下,期约可以落定(settled)为代表成功的兑现(fulfilled)状态,或者代表失败的拒绝(rejected)状态。每个期约只要状态切换为兑现(fulfilled),就会有一个私有的内部值(value)。类似地,每个期约只要状态切换为拒绝(rejected),就会有一个私有的内部理由(reason)。无论是值还是理由,都是包含原始值或对象的不可修改的引用。二者都是可选的,而且默认值为undefined。在期约到达某个落定(settled)状态时执行的异步代码始终会收到这个值(value)或理由(reason)。

Promise.resolve()

通过调用Promise.resolve()静态方法,可以实例化一个解决的期约。

 //下面两个期约实例实际上是一样的:
 let p1 = new Promise((resolve, reject) => resolve());
 let p2 = Promise.resolve();

这个解决的期约的值(value)对应着传给Promise.reslove()的第一个参数。使用这个静态方法,实际上可以把任何值都转换为一个期约:

    setTimeout(console.log, 0, Promise.resolve());  //Promise {<resolved>: undefined}
    setTimeout(console.log, 0, Promise.resolve(3)); //Promise {<resolved>: 3}
    //多余的参数会忽略
    setTimeout(console.log, 0, Promise.resolve(3, 4, 5)); //Promise {<resolved>: 3}

Promise.resolve()可以说是一个幂等方法。所谓的幂等是指多个请求返回相同的结果。用数学表单的话: X^Y = X

    let p = Promise.resolve(6);
    setTimeout(  console.log, 0, p === Promise.resolve(p)); // true
    setTimeout(  console.log, 0, p === Promise.resolve(Promise.resolve(p))); // true

Promise.reject()

Promise.resolve()类似,Promise.reject()会实例化一个拒绝的期约(Promise)并抛出一个异步错误(这个错误不能通过try/catch捕获。而只能通过拒绝处理程序捕获)。

    //下面两个期约实例实际上是一样的:
    let p1 = new Promise((resolve, reject) => reject());
    let p2 = Promise.reject();

这个拒绝的期约的理由就是传给Promise.reject()的第一个参数。这个参数也会传给后续的拒绝处理程序:

    let p = Promise.reject(3);
    setTimeout(console.log, 0, p);  //Promise {<rejected>: 3}
    p.then(null, (e) => setTimeout(console.log, 0, e));     //3

关键在于,Promise.reject()并没有照搬Promise.resolve()的幂等逻辑。如果给它传一个期约(Promise)对象,则这个期约会成为它返回的拒绝(rejected)期约的理由:

        setTimeout(console.log, 0, Promise.reject(Promise.resolve()));
        //Uncaught (in promise) 
        //Promise {<resolved>: undefined}
        //Promise {<rejected>: Promise}

Promise.prototype.then()

这个then()方法接收最多两个参数: onResolved处理程序和onRejected处理程序。这两个参数都是可选的,如果提供的话,则会在期约分别进入"兑现"和"拒绝"状态时执行。

上面用到了Promise.prototype.then()方法,该方法返回一个新的期约实例。

    let p1 = new Promise(() => {});
    let p2 = p1.then();
    setTimeout(console.log, 0, p1 === p2); // false
  1. 这个新的期约实例基于onResolved处理程序的情况如下:

then()方法的回调中没有传入返回值的话,也就是如果没有显式的返回语句,则Promise.resolve()会包装默认的返回值:undefined。

    let p1 = Promise.resolve('foo');
    let p2 = p1.then(() => {}); 
    let p3 = p1.then(( => Promise.resolve());
    setTimeout(console.log, 0, p2); // Promise {<resolved>: undefined}
    setTimeout(console.log, 0, p3); // Promise {<resolved>: undefined}

如果有显式的返回值,则Promise.resolve()会包装这个值。

    let p4 = p1.then(() => 'bar'); 
    let p5 = p1.then(( => Promise.resolve('bar'));
    setTimeout(console.log, 0, p4); // Promise {<resolved>: "bar"}
    setTimeout(console.log, 0, p5); // Promise {<resolved>: "bar"}

抛出异常会返回拒绝的期约:

    let p6 = p1.then(() => {throw 'baz';});  // Uncaught (in promise) baz
    setTimeout(console.log, 0, p6);      //Promise {<rejected>: "baz"}

注意:返回错误值不会触发上面的拒绝行为,而会把错误对象包装在一个解决的期约中:

    let p7 = p1.then(() => Error('err'));
    setTimeout(console.log, 0, p7);     //Promise {<resolved>: Error: err
    at <anonymous>:1:24}
  1. 在基于onRejected处理程序时: 跟onResolved的类似。

onRejected处理程序返回的值也会被Promise.resolve()包装。在抛出异常或传入返回Promise.reject()时才会返回拒绝的期约。

    let p1 = Promise.reject('foo');
    let p2 =  P1.then(null, () => {});  //Promise {<resolved>: undefined}

    let p3 = p1.then(null, () => Promise.resolve());    //Promise {<resolved>: undefined}

    let p4 = p1.then(null, () => Promise.reject());     //Promise {<rejected>: undefined}

    let p5 = p1.then(null, () => {throw 'baz';});    // Promise {<rejected>: "baz"}

    let p6 = p1.then(null, () => Error('qux'));     // Promise {<resolved>: Error: qux at <anonymous>:1:26}

Promise.prototype.catch()

待续。

Promise的应用场景:

可以解决多请求,合并请求处理错误,多验证的场景。

Tips: 同步是有序的进入内存运行
而期约的异步形式是期约的处理程序是按照它们添加的顺序执行的,是先添加到“消息队列”

  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值