美文网首页
Promise整理

Promise整理

作者: 盛夏晚清风 | 来源:发表于2018-02-21 11:11 被阅读0次

在开发过程中,我们经常需要处理异步的情况,开发人员对异步的处理方式也从轮询到回调,再到现在的Promise。于是,我打算对Promise整理一番。

Promise类似于XMLHttpRequest,通过构造函数Promise来创建一个新Promise对象作为接口。要想创建一个promise对象,可以使用new来调用Promise的构造器实例化:

var promise=new Promise(function(resolve,reject){
    //异步处理
    //处理结束后,调用resolve或reject
})

Promise的状态

用new Promise实例化的对象有三个状态:

  • Fulfilled:resolve(成功)时,此时会调用onFulfilled;
  • Rejected:reject(失败)时,此时会调用onRejected;
  • Pending:既不是resolve也不是reject的状态,也就是promise对象刚被创建后的初始化状态。

Promise.resolve

Promise.resolve(value)可以认为是以下代码的语法糖:

new Promise(function(resolve){
    resolve(value); 
});

在这段代码中的resolve(value);会让这个promise对象立即进入确定(即resolved)状态,并将value传递给后面then里所指定的onFulfilled函数。

方法Promise.resolve(value);的返回值也是一个promise对象,所以我们可以像下面那样接着对其返回值进行.then调用:

Promise.resolve(value).then(function(value){
    console.log(value);
})

Promise.resolve方法的另一个作用就是将thenable对象转换为promise对象。

thenable,简单来说是一个非常类似于promise的东西,它指一个具有.then方法的对象。例如jQuery.ajax(),它的返回值是一个具有.then方法的jqXHR Object对象,这个对象继承了来自Deferred Object的方法和属性。但是Deferred Object并没有遵循Promises/A+或ES6 Promises标准,所以即使看上去这个对象转换成了一个promise对象,但是二者的then方法机制不同。

将thenable对象转换成promise对象:

var promise=Promise.resolve($.ajax(...));
promise.then(function(value){
    console.log(value);
});

简单总结一下Promise.resolve方法的话,可以认为它的作用就是将传递给它的参数填充(Fulfilled)到promise对象后并返回这个promise对象,它的参数主要分为以下三类:

  1. 接收到promise对象参数时:返回该promise对象
  2. 接收到thenable类型的对象时:返回一个新的promise对象,该对象具有一个then方法;
  3. 接收到其他类型的参数(或者参数为空)时:返回一个将该参数作为值的新promise对象

另外,调用resolve或reject并不会终结Promise的参数函数的执行:

var promise = new Promise(function (resolve){
    console.log("promise1"); 
    resolve(42);
    console.log("promise2"); 
});
promise.then(function(value){
    console.log(value);
});
结果:

上面代码中,虽然在调用了 resolve(42)之后打印promise2,但是实际上promise2先打印出来。

Promise.reject

Promise.reject(error)可以认为是以下代码的语法糖:

new Promise(function(resolve,reject){
    reject(new Error("出错了")); 
});

Promise只能进行异步操作?

promise是同步的,.then是异步的(规定:Promise只能使用异步调用方式):

var promise = new Promise(function (resolve){
    console.log("inner promise"); 
    resolve(42);
});
promise.then(function(value){
    console.log(value);
});
console.log("outer promise"); 
结果:

依照结果来看,打印出"inner promise"后紧接着打印出了"outer promise",最后才调用.then方法打印出value。所以为了避免同步调用和异步调用同时存在导致的混乱,即使.then方法可以立即调用(即同步调用),Promise也会以异步的方式调用该回调函数,这是在Promise设计上的规定方针

所以这个方针也告诉我们,如果我们的回调函数可能会同步调用,也可能异步调用,最好选择同一使用异步调用的方式。例如,将代码:

function onReady(fn) {
    var readyState = document.readyState;
    if (readyState === 'interactive' || readyState === 'complete') {
        fn();    // 注意这里
    } else {
        window.addEventListener('DOMContentLoaded', fn);
    }
}
onReady(function () {
    console.log('DOM fully loaded and parsed');
});
console.log('==Starting==');

中的fn改为:

setTimeout(fn, 0);

这样,同步的fn回调就变为了异步的fn回调。

Promise.all

Promise.all接收一个promise对象的数组作为参数,当这个数组里的所有promise对象全部变为resolve或reject状态时,它才会去调用.then方法,并且.then方法中的的执行结果的参数顺序与all()中各promise对象的顺序一致。

举例:

var promise1=ajax({...});
var promise2=ajax({...});
Promise.all([promise1,promise2]).then(fn);

只有promise1和promise2都完成了,才会去调用then方法。

注意点:传递给Promise.all的promise并不是一个个顺序执行的,而是同时开始、并行执行的。对于上面的例子,promise1和promise2同时开始、并行执行。

Promise.race

Promise.race接收一个promise对象的数组作为参数,当这个数组里的所有promise对象中只要有一项变为resolve或reject状态时,它就会去调用.then方法,并且.then方法中的的执行结果的参数即为该promise对象的回调参数。

举例:

var promise1=ajax({...});
var promise2=ajax({...});
Promise.race([promise1,promise2]).then(fn);

只要promise1和promise2其中有一个完成,就会去调用then方法。

注意点:当Promise.race中的第一个promise对象变为确定(fulfilled)状态后,它之后的promise对象会继续运行,不会取消或者中断。对于上面的例子,只要promise1或者promise2其中某一个变为确定态,就会去调用then方法。

其他注意点

  1. .catch是语法糖,promise.catch(function(error){...})等价于promise.then(undefined,function(error){...})

  2. 每次调用then都会返回一个新创建的promise对象

  3. 使用promise.then(onFulfilled, onRejected)时,如果onFulfilled中发生异常,在onRejected中是捕获不到这个异常的;而在promise.then(onFulfilled).catch(onRejected)中,.then中的异常能在.catch中捕获。

  4. 使用reject而非throw

由于个人水平有限,博客错误之处,烦请指正!

参考资料:
1、JavaScript Promise迷你书
2、Promise/A+规范

相关文章

  • Promise整理

    在开发过程中,我们经常需要处理异步的情况,开发人员对异步的处理方式也从轮询到回调,再到现在的Promise。于是,...

  • 详解ES6 Promise

    整理Promise提供的各种方法和错误处理方法。 1.Promise.resolve() 1.1 Promise....

  • Promise API与局限性

    @NOTE 阅读完你不知道的JS---Promise后 重新整理Promise使用方式 new Promise(....

  • Promise的整理

    Promise语法用了很久,还没有好好整理过。 语法 new Promise((resolve,reject)=>...

  • Promise

    前言 回过头来整理下Promise Promise Promise的一些基本点3个state:pendingful...

  • promise

    本文是整理阮一峰大神ES6中 Promise 的学习笔记 目录: Promise.prototype.then()...

  • Promise (Bluebird) 笔记整理

    1. 基本用法 **例 1.1 创造一个Promise实例 ** 例 1.2 用then方法分别指定Resolve...

  • 初识Promise

    这是一篇很初级的有关Promise的知识整理,还有很多的知识点正在进行中... 什么是Promise Promis...

  • 如何从无到有实现Promise(上)

    前言 最近整理了两篇关于js异步的笔记,谈到异步就不得不说说 Promise。Promise 取代传统回调方式实现...

  • 手写promise

    面试的笔试题中遇到过手写promise的题目,以下是参考了网上的文章,自己整理的一个简单的promise函数:

网友评论

      本文标题:Promise整理

      本文链接:https://www.haomeiwen.com/subject/mzuuvxtx.html