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
  • 相关阅读:
    target runtime apache v6.0 not defined解决
    java.lang.AbstractMethodError: javax.servlet.jsp.JspFactory.getJspApplicationContext(Ljavax/servlet/ServletContext;)Ljavax/servlet/jsp/JspApplicationContext;
    The valid characters are defined in RFC 7230 and RFC 3986问题
    invalid END header解决方法
    You have more than one version of ‘org.apache.commons.logging.Log’ visible, which is not allowed问题解决
    Invalid character found in the request target. The valid characters are defined in RFC 7230 and RFC 3986
    在eclipse中import java web项目时遇到的一些问题并将该项目通过tomcat发布
    java byte转string 涉及到字节流中有中文
    spring+mybatis框架搭建时遇到Mapped Statements collection does not contain value for...的错误
    试试看读一下Zepto源码
  • 原文地址:https://www.cnblogs.com/xiaonian8/p/13847243.html
Copyright © 2011-2022 走看看