• es6学习笔记--promise对象


    Promise对象是为了简化异步编程。解决回调地狱情况
    Promise,简单说就是一个容器,里面保存着某个未来才会结束的事件(通常是一个异步操作)的结果。从语法上说,Promise 是一个对象,从它可以获取异步操作的消息。
    Promise对象用于延迟(deferred) 计算和异步(asynchronous ) 计算。一个Promise对象代表着一个还未完成,但预期将来会完成的操作。
    Promise是一个对象,可以用构造函数来创建一个Promise实例。
    let promise = new Promise((resolve, reject) =>{
        // .... some coding
        if (true){   // 异步操作成功
            resolve(value);
        } else {
            reject(error);
        }
    })
    promise.then(value=>{
        // 成功的回调函数
    }, error=>{
        // 失败后的回调函数
    })
    params:传参是一个回调函数。这个回调函数有两个参数resolve和reject。
        resolve: 将Promise对象的状态从“未完成”变为“成功”(即从 pending 变为 resolved),在异步操作成功时调用,并将异步操作的结果,作为参数传递出去.
          (简单来说就是成功了的执行)
        reject: 将Promise对象的状态从“未完成”变为“失败”(即从 pending 变为 rejected),在异步操作失败时调用,并将异步操作报出的错误,作为参数传递出去。
          (简单来说就是失败了的执行)
    promise之后then的参数:
        第一个参数是成功的回调函数,必选
        第二个参数是失败的回调函数,可选
    let promise = new Promise((resolve, reject) =>{
        console.log('开始')
        if (2 > 1){   // 异步操作成功
            resolve({name:'peter',age:25});
        } else {
            reject(error);
        }
    })
    promise.then(value=>{
        // 成功的回调函数
        console.log(value)
    }, error=>{
        // 失败后的回调函数
        console.log(error)
    })
    // 开始
    // {name: "peter", age: 25} 
    let promise = new Promise((resolve, reject) =>{
        console.log('开始')
        if (2 > 3){   // 异步操作成功
            resolve(a);
        } else {
            reject('未知错误');
        }
    })
    promise.then(value=>{
        // 成功的回调函数
        console.log(value)
    }, error=>{
        // 失败后的回调函数
        console.log(error)
    })
    // 开始
    // 未知错误

    Promise的特点:

      1 对象的状态不受外界影响。Promise对象代表一个异步操作,有三种状态:pending(进行中)、fulfilled(已成功)和rejected(已失败)。只有异步操作的结果,可以决定当前是哪一种状态,任何其他操作都无法改变这个状态。
      2 一旦状态改变,就不会再变,任何时候都可以得到这个结果。就是成功了就一直是成功的状态,失败一直是失败的状态

    promise先按顺序实行完promise实例中方法再实行then中的resolve或者reject.

    let promise = new Promise((resolve, reject)=>{
        console.log('promise')
        if (2 > 1){   // 异步操作成功
            resolve({name:'peter',age:25});
        } else {
            reject(error);
        }
        console.log('end')
    })
    promise.then(
        value=>{
            console.log(value)
        },
        error=>{
            console.log(error)
        }
    )
    // promise
    // end 
    // {name: "peter", age: 25}

    promise封装Ajax的例子

    const getJSON = function (url) {
        const promise = new Promise(function (resolve, reject) {
            const handler = function () {
                if (this.readyState !== 4) {
                    return;
                }
                if (this.status === 200) {
                    resolve(this.response);
                } else {
                    reject(new Error(this.statusText));
                }
            };
            const client = new XMLHttpRequest();
            client.open("GET", url);
            client.onreadystatechange = handler;
            client.responseType = "json";
            client.setRequestHeader("Accept", "application/json");
            client.send();
        });
        return promise;
    };
    
    getJSON("xxxxx").then(function (json) {
        console.log('Contents: ' + json);
    }, function (error) {
        console.error('出错了', error);
    });
    Promise方法:

    then() 为 Promise 实例添加状态改变时的回调函数 ,上面已经提起过.

    params: 第一个参数是resolved状态的回调函数, 必选
        第二个参数是rejected状态的回调函数, 可选
    ps: then方法返回的是一个新的Promise实例(注意,不是原来那个Promise实例)。因此可以采用链式写法,即then方法后面再调用另一个then方法。
    function start() {
        return new Promise((resolve, reject) => {
            resolve('start');
        });
    }
    start()
        .then(data => {
            // promise start
            console.log(data);
            return Promise.resolve(1); // p1
        })
        .then(data => {
            // promise p1
            console.log(data);
        })
    // start
    // 1

    promise的链式编程,就是第一个的Promise实例的返回的值作为下一个Promise实例的参数。

    catch() 用于指定发生错误时的回调函数 和then一样,存在链式

    返回一个Promise对象,如果该对象状态变为resolved,则会调用then方法指定的回调函数;如果异步操作抛出错误,状态就会变为rejected,就会调用catch方法指定的回调函数,处理这个错误。
    function start() {
        return new Promise((resolve, reject) => {
            resolve('start');
        });
    }
    start()
        .then(data => {
            // promise start
            console.log(data);
            return Promise.reject(1); // p1
        })
        .catch(data => {
            // promise p1
            console.log(data);
        })

    ps:then方法指定的回调函数,如果运行中抛出错误(reject),也会被catch方法捕获。如果运行中是正确的,则不会实行catch语句,而是then的回调

    function start() {
        return new Promise((resolve, reject) => {
            if(2>3){
                resolve('start');
            }else{
                reject('error')
            }
        });
    }
    start()
        .then(data => {
            console.log(data);
        })
        .catch(data => {
            console.log(data);
        })
    // error

    try catch方法等价于promise 抛出错误:

    // 写法一
    const promise = new Promise(function(resolve, reject) {
        try {
            throw new Error('test');
        } catch(e) {
            reject(e);
        }
    });
    promise.catch(function(error) {
        console.log(error);
    });
    
    // 写法二
    const promise = new Promise(function(resolve, reject) {
        reject(new Error('test'));
    });
    promise.catch(function(error) {
        console.log(error);
    })
    如果链式中,写了then和catch语句,运行正确,则会进行下一个then,在这个then中运行错误,则会抛出这个之后的catch而不是上一个catch
    function start() {
        return new Promise((resolve, reject) => {
            if(4>3){
                resolve('start');
            }else{
                reject('error')
            }
        });
    }
    start()
        .then(data => {
            console.log(data);
            return Promise.resolve(1)
        })
        .catch(data => {
            console.log(data)
        })
        .then(data => {
            console.log(data)
            return Promise.reject(2)
        })
        .catch(data => {
            console.log(data);
        })
    // start
    // 1
    // 2

    finally() 不管promise最后的状态,在执行完then或catch指定的回调函数以后,都会执行finally方法指定的回调函数

    finally方法不接受任何回调函数作为参数,因此不知道Promise对象是resolve还是reject。该方法与Promise状态无关,不依赖其执行结果。
    function promise(){
        return new Promise((resolve, reject) => {
            resolve('success');
        })
    };
    promise().then(data => {
        console.log(data)
        return Promise.reject('fail')
    }).catch(data =>{
        console.log(data)
    }).finally(() => {
        console.log('end')
    })
    // success
    // fail
    // end

    Promise.all() 将多个 Promise 实例,包装成一个新的 Promise 实例。并行执行异步操作的能力,并且在所有异步操作执行完后才执行回调

    const allPromise = Promise.all([p1, p2, p3])
    上述代表将p1,p2,p3这些Promise实例包装成allPromise,参数不一定是数组,只要是有遍历结构就可以作为参数。
    从而该实例的状态有两种情况:
      1: 当所有的状态都是resolve时,allPromise的状态是resolve
      2:当有一个状态是reject,allPromise的状态取决于第一次reject的状态。
    当全部状态为resolve时。
    function promise(){
        return new Promise((resolve, reject) => {
            console.log(1)
            resolve('第一个');
        })
    };
    function promise1(){
        return new Promise((resolve, reject) => {
            console.log(2)
            resolve('第二个');
        })
    };
    function promise2(){
        return new Promise((resolve, reject) => {
            console.log(3)
            resolve('第三个');
        })
    };
    Promise.all([promise(), promise1(), promise2()])
    .then(data => {
        console.log(data)
    })
    .catch(data => {
        console.log(data)
    })
    // 1
    // 2
    // 3
    // [1,2,3]
    当全部状态中有一个是reject时
    function promise(){
        return new Promise((resolve, reject) => {
            console.log(1)
            resolve('第一个');
        })
    };
    function promise1(){
        return new Promise((resolve, reject) => {
            console.log(2)
            reject('第二个');
        })
    };
    function promise2(){
        return new Promise((resolve, reject) => {
            console.log(3)
            resolve('第三个');
        })
    };
    Promise.all([promise(), promise1(), promise2()])
    .then(data => {
        console.log(data)
    })
    .catch(data => {
        console.log(data)
    })
    // 1
    // 2
    // 3
    // 第二个
    Promise.all()可以适用于初始化的场景

    Promise.race() 将多个 Promise 实例,包装成一个新的 Promise 实例。

    和Promise.all()的用法一样,唯一不同的是,Promise实例中谁先执行,就先返回执行那一方的回调函数(resolve和reject同样的道理,谁先执行就执行谁的回调函数)
    function promise(){
        return new Promise((resolve, reject) => {
            setTimeout(function(){
                console.log(1);
                resolve('第一个');
            }, 4000);
        })
    };
    function promise1(){
        return new Promise((resolve, reject) => {
            setTimeout(function(){
                console.log(2);
                resolve('第二个');
            }, 2000);
        })
    };
    function promise2(){
        return new Promise((resolve, reject) => {
            setTimeout(function(){
                console.log(3);
                resolve('第三个');
            }, 3000);
        })
    };
    Promise.race([promise(),promise1(), promise2()])
    .then(data => {
        console.log(data)
    })
    .catch(data => {
        console.log(data)
    })
    // 2 
    // 第二个
    // 1
    // 3
    该方法可以适用于请求超时触发回调

    Promise.resolve() 返回一个新的Promise实例,并且状态为resolve。

    function fn(){
        console.log('success')
        return 1
    }
    Promise.resolve(fn())
    .then(data => {
        console.log(data)
    })
    // success
    // 1

    Promise.reject() 返回一个新的Promise实例,并且状态为reject。

    function fn(){
        console.log('fail')
        return 2
    }
    Promise.reject(fn())
    .then(data => {
        console.log(data)
    })
    .catch(data => {
        console.log(data)
    })
    // fail
    // 2

     有了Promise对象,就可以把异步操作以同步操作的流程表达出来,避免了层层嵌套的回调函数。此外,Promise对象提供了统一的接口,使得控制异步操作更加容易。

    对应的笔记和实例,我放到了GitHub,https://github.com/sqh17/notes

    有什么问题请私信或留下评论,一起加油。

     
     
    参考资料:
    阮一峰大大的es6标准入门:http://es6.ruanyifeng.com
  • 相关阅读:
    SSM,即Spring+SpringMVC+MyBatis三个开源框架的整合框架集。
    doAfterBody()方法是在( )接口中定义的。
    考虑下面两个JSP文件代码片断: test1.jsp:
    下列JSP代码:
    以下web.xml片断( )正确地声明servlet 上下文参数。
    以下( )可用于检索session属性userid的值。
    有关Servlet的生命周期说法正确的有( )。
    关于Web应用程序,下列说法错误的是( )。
    如何创建Cookie? (选择1项)
    HttpServlet中,用来处理POST请求的方法是(选择1项)
  • 原文地址:https://www.cnblogs.com/sqh17/p/8625263.html
Copyright © 2020-2023  润新知