zoukankan      html  css  js  c++  java
  • ES6之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 状态,无法得知目前进行到哪一阶段(刚开始还是快结束)

    广州设计公司https://www.houdianzi.com 我的007办公资源网站https://www.wode007.com

    如何使用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
  • 相关阅读:
    log日志框架和LocationAwareLogger问题
    Eclipse 各种小图标的含义
    自定义log4j日志级别
    在Tomcat配置JNDI数据源的三种方式
    mybatis中"#"和"$"的区别
    Postman用法简介-Http请求模拟工具
    mustache模板技术(转)
    VS的编译选项
    Java Service Wrapper简介与使用
    还活着
  • 原文地址:https://www.cnblogs.com/xiaonian8/p/13847243.html
Copyright © 2011-2022 走看看