ES6之Promise

更新日期: 2020-02-19阅读: 2.3k标签: Promise

前言

Promise,用于解决回调地域带来的问题,将异步操作以同步的操作编程表达出来,避免了层层嵌套的回调函数


什么是 Promise

所谓的 promise,简单的来说就是一个容器,里面保存着某个未来才会结束的事件(也就是我们的异步操作)的结果。从语法上面来说,Promise 是一个对象,从它可以获取异步操作的消息。Promise 提供统一的 api,各种异步操作都可以用同样的方法进行处理。


Promise特性

promise 对象代表一个异步操作,有三种状态:pending、fulfilled、reject

任何其他状态都无法改变这个状态。这也是 Promise 这个名字的由来。'承诺'表示其他手段无法改变它的状态。


Promise 的出现解决什么问题

promise其实就是一个异步编程方案,在 promise 出现之前总会遇到所谓的'回掉地域'的嵌套代码

    step(1, function() {
        step(2, function() {
            step(3, function() {
                ……….
            })
        })
    })

都知道这种"回调地狱",是一种很让人恼火的代码书写格式,嵌套多层之后会让人阅读起来怀疑人生的。但是这种"回调地狱"真的就只有格式的问题嘛?显然不是。


引用例子

一个来自《YDKJS》的例子:一个程序员开发了一个付款的系统,它良好的运行了很长时间。突然有一天,一个客户在付款的时候信用卡被连续刷了五次。这名程序员在调查了以后发现,一个第三方的工具库因为某些原因把付款回调执行了五次。在与第三方团队沟通之后问题得到了解决。

上面的例子就是一个 信任问题 回调函数的方式会引发很多信任问题,例如重复调用,调用太晚等等问题。那么promise怎么解决上述两个问题的呢?


Promise意义

可读性 首先是 Promise 的 then 方法,支持我们在回调写在 then 方法中,让我们在日常开发中可以很清楚的看到,比如上面的代码就可以改写成

     Promise.resolve(1).
     .then(step => ++setp)
     .then(step => ++setp)
     .then(step => ++setp)
 ...

Promise 承诺的严谨性 它与普通的回调方式的区别在于

普通方式,回调成功之后的操作直接写在了回调函数里面,而这些操作的调用是由第三方控制

Promise方式 回调只负责成功之后的通知,而回调成功之后的操作放在 then 的回调函数里面,由 Promise 精确控制。

注意 Promise 的状态不可逆。一旦发生改变就没有办法改变成任何一种状态。Promise 只能是异步的,所以不会出现异步的同步调用。


Promise缺点

无法取消 Promise 一旦新建它就会立即执行,无法中途取消

如果不设置回调函数,Promise 内部抛出的错误不会反应到外部。

当处于 pending 状态,无法得知目前进行到哪一阶段(刚开始还是快结束)


如何使用Promise

Promise 对象是一个构造函数,用来生成 Promise 实例

Promise 构造函数接收一个函数作为参数,该函数的两个参数分别是 resolve 和 reject,这两个参数也函数,由 JavaScript 提供,不需要自己添加

Promise实例生成以后,可以用then方法分别指定resolved状态和rejected状态的回调函数。但一般不建议给then加两个参数,建议使用.then完成resolved状态的操作,使用.catch完成rejected的操作。 像这样:

    const promise = new Promise( (resolve,reject) => {
        resolve('ok');
        reject('error')
    })
    promise.then(res => {
        console.log(res)
    }).catch(err => {
        console.log(err)
    })

还可以用promise实现ajax的操作:

const getJSON = function(url){
        const promise = new Promise((resolve,reject) => {
            const handler = function(){
                if(this.readyState !== 4){//这两个if语句主要用来判断请求是否成功
                    return;
                };
                if(this.status === 200){
                    resolve(this.response)//这是成功请求后,将返回的数据传到回调函数中
                }else{
                    reject(new Error(this.statusText))//这是失败后,将原因返给catch
                }
            };
            const xmlHttp = new XMLHttpRequest();//声明一个XMLHttpRequest对象的实例
            xmlHttp.open("get", url);//设置要发送的方法和地址
            xmlHttp.onreadystatechange = handler;//在这里调用上面定义的handler
            xmlHttp.responseType = "json";
            xmlHttp.setRequestHeader("Accept", "application/json");//设置请求头,规定接受json类型的数据
            xmlHttp.send();//真正的发送请求
        });
        return promise;
    };
    getJSON("url").then( res => {
        //成功后的操作
    }).catch(err => {
        //失败后的提示
    })

Promise可以嵌套使用,就是将一个Promise实例作为另一个Promise实例的resolve方法的参数传入。

说说then方法,这个方法是定义在Promise的原型上的,then方法返回的是一个新的Promise实例,因此可以采用链式写法,即then方法后面调用另一个then方法。

再来说几个Promise常用的api吧!

Promise.prototype.finally():

Finally方法用于不管promise对象的最后状态如何,都会执行的操作

promise
.then(result => {···})
.catch(error => {···})
.finally(() => {···});

Promise.resolve():

这个方法用来将参数转变成Promise对象

参数是一个Promise实例:不改动

参数是一个thenable对象:会将这个对象转为 Promise 对象,然后就立即执行thenable对象的then方法。

参数不是具有then方法的对象,或根本就不是对象:返回一个新的Promise对象,状态为resolved

不带有任何参数:直接返回一个ersolved状态的Promise对象

Promise.reject() Promise.reject(reason)方法也会返回一个新的 Promise 实例,该实例的状态为rejected

Promise.all():

const p = Promise.all([p1, p2, p3]);

用于将多个Promise实例,包装成一个新的Promise实例。这个方法接收一个数组作为参数,且都是Promise实例,如果不是,就会先调用Promise.resolve方法。 注意: 只有当数组中的实例的状态都是fulfilled,p才会变成fulfilled,此时,p1,p2,p3的返回值组成一个数组,传递给p的回调函数。 只要p1、p2、p3之中有一个被rejected,p的状态就变成rejected,此时第一个被reject的实例的返回值,会传递给p的回调函数。

Promise.race(): 和all方法类似,也是讲多个Promise实例包装成一个。 但不一样的是,只要p1、p2、p3之中有一个实例率先改变状态,p的状态就跟着改变。那个率先改变的 Promise 实例的返回值,就传递给p的回调函数。

在实际开发中,我们总希望让同步函数同步执行,异步函数异步执行,但如果同步函数想用Promise来做处理,能否实现同步呢?答案是肯定的。 这就要说到**Promise.try()**方法了

const f = () => console.log('now');
Promise.try(f);
console.log('next');
// now// next

链接: https://fly63.com/article/detial/7497

你真的了解 Promise 吗?Promise 必知必会(十道题)

Promise 想必大家十分熟悉,想想就那么几个 api,可是你真的了解 Promise 吗?本文根据 Promise 的一些知识点总结了十道题,看看你能做对几道。

剖析Promise内部结构,一步一步实现一个完整的、能通过所有Test case的Promise类

本文写给有一定Promise使用经验的人,如果你还没有使用过Promise,这篇文章可能不适合你,Promise标准中仅指定了Promise对象的then方法的行为,其它一切我们常见的方法/函数都并没有指定.

Async/Await替代Promise的6个理由

Async/Await替代Promise的6个理由:Async/Await是近年来JavaScript添加的最革命性的的特性之一。它会让你发现Promise的语法有多糟糕,而且提供了一个直观的替代方法。

Promise 原理解析与实现(遵循Promise/A+规范)

Promise是JS异步编程中的重要概念,异步抽象处理对象,是目前比较流行Javascript异步编程解决方案之一,Promise 是一个构造函数, new Promise 返回一个 promise对象 接收一个excutor执行函数作为参数

简单模仿实现 Promise 的异步模式

这篇文章是考虑如何自己实现一个简单 Promise,用以理解 Promise。和原生 Promise的调用方法一样,支持链式调用,本文实现的方法只能用于参考Promise的原理,还有很多特性没有实现,比如 race,all 方法的实现。

数组的遍历你都会用了,那Promise版本的呢

在对数组进行一些遍历操作时,发现有些遍历方法对Promise的反馈并不是我们想要的结果。async/await为Promise的语法糖,文中会直接使用async/await替换Promise;map可以说是对Promise最友好的一个函数了,

Promise使用时应注意的问题

最近在使用axios库时遇到了个问题,后端接口报了500错误,但前端并未捕获到。在axios整体配置的代码中,过滤http code时,调用了filter401()、filter500(),但是这里注意并未将两个filter函数的结果返回,也就是并未返回promise,这就是导致问题出现的原因

es6 Promise 的基础用法

想必接触过Node的人都知道,Node是以异步(Async)回调著称的,其异步性提高了程序的执行效率,但同时也减少了程序的可读性。如果我们有几个异步操作,并且后一个操作需要前一个操作返回的数据才能执行

关于 Promise 的 9 个提示

你可以在 .then 里面 return 一个 Promise,每次执行 .then 的时候都会自动创建一个新的 Promise,对调用者来说,Promise 的 resolved/rejected 状态是唯一的,Promise 构造函数不是解决方案,使用 Promise.resolve

手写一款符合Promise/A+规范的Promise

Promise的一些用法在此不多赘述,本篇主要带领你手写一个Promise源码,学完你就会发现:Promise没有你想象中的那么难.本篇大概分为以下步骤:实现简单的同步Promise、增加异步功能、增加链式调用then、增加catch finally方法、增加all race 等方法、实现一个promise的延迟对象defer、最终测试

点击更多...

内容以共享、参考、研究为目的,不存在任何商业目的。其版权属原作者所有,如有侵权或违规,请与小编联系!情况属实本人将予以删除!