zoukankan      html  css  js  c++  java
  • Promise 基础使用

    为什么要使用Promise

    JS 是一门单线程单线程的语言,所以在早期解决异步的场景时,大部分情况下是使用回调函数的形式。

    例如我们在浏览器中发送一个ajax请求。发送请求之后要过一段时间,浏览器响应之后才会返回给我们结果,如果我们希望在异步请求之后进行某些操作,那么只能通过回调函数来进行。

    var syncFunc = function(cb) {
        setTimeout(function() {
            cb();
        }, 1000);
    }
    
    syncFunc(function() {console.log(1234)});
    
    $.ajax(url, method, function() {});

    像上面的例子,syncName 就是一个异步函数,里面的setTimeout会在1s 之后执行传入的回调函数 cb 。按照上面的方式,在1s之后会打印123。

    同样,如果后续还有内容需要在异步函数结束之后操作的话,就需要多个异步函数嵌套,非常不利于维护和阅读。

    setTimeout(function() {
        console.log(111);
        setTimeout(function() {
            console.log(222);
            // ...
        }, 1000);
    }, 1000);

    为了能使回调函数以更加优雅的方式进行调用,在ES6中就产生了一个 Promise 的新的规范,他让异步操作变得几乎像是同步的操作。

    Promise 的使用

    在支持ES6的现代浏览器环境中,我们可以直接使用 new Promise() 就可以创建一个Promise实例。

    这个构造函数接受一个函数,分别接受两个参数。resolve 和 reject, 表示我们需要改变当前实例的转态到 已完成 或者 已拒绝

    function promise1() {
        return new Promise(function(resolve, reject) {
            // 定义异步
            setTimeout(function() {
                console.log('promise1');
                // 最后调用传入的 resolve 函数,将该Promise 实例标记为已完成
                resolve();
            }, 1000);
        });
    }
    function promise2() {
        return new Promise(function(resolve, reject) {
            setTimeout(function() {
                console.log('promise2');
                resolve();
            }, 1000);
        });
    }

    上面两个Promise 实例直接链式调用就可以按顺序执行:

    promise1().then(function() {return promise2();});
    // 或者简写成
    promise1().then(promise2);

    上面的代码在浏览器中执行后,就能看到在1s后输出promise1 ,再过1s后输出promise2。从这个demo我们可以看到,当前Promise如果转态变为已完成,即执行了resolve方法治好,就会立即去执行then方法中的下一个Promise实例。

    如果我们的Promise实例转态变为了已拒绝,即执行了reject方法,那么就会进入后续的异常处理函数中。

    function promise3() {
        return new Promise(function(resolve, reject) {
            var random = Math.random() * 10; 随机生成一个0-10 的随机数
            setTimeout(function() {
                if (random > 5) {
                    reject(random);
                } else {
                    resolve(random);
                }
            }, 1000);
        });
    }
    
    var onResolve = function(val) {
        console.log('resolve input::', val);
    }
    var onReject = function(val) {
        console.log('reject input::', val);
    }
    
    // Promise的.then 方法也可以接收两个函数,第一个函数作为`resolve`后执行,第二个函数作为`reject`后执行
    promise3().then(onResolve, onReject);
    
    // 也可以通过 .catch 拦截变为已拒绝的Promise
    promise3()
        .catch(onReject)
        .then(onResolve);
    
    // 也可以通过 try catch 进行拦截变为已拒绝的 Promise
    try {
        promise3.then(onReject);
    } catch(e) {
        onReject(e);
    }

    这个例子使用了三种方式来拦截Promise变为已拒绝的状态,分别是then的第二个参数,.catch方法捕获抛出的异常,try catch 拦截代码块中的错误。

    我们在改变Promise状态是调用的resolev 和reject 函数的时候,也可以向下一步的then或者catch中传递参数。

    同时,我们好可以发现,我们早改变Promise转态的时候,还可以给下一步then或者catch中传递参数。

    总结一下:

    1. Promise有三种转态,进行中已完成已拒绝,进行中的转态可以更改为已完成或者已拒绝,已经更改过的转态无法继续更改。

    2. ES6中的Promise构造函数,我们构造后需要传入一个函数,这个函数接受两个参数,即resolvereject,执行resolve后,当前Promise变为已完成转态,执行reject之后,当前Promise变为已决绝转态。

    3. 通过.then方法,即可在上一个Promise达到已完成时继续执行下一个函数或者下一个Promise,同时可以通过resolve或者reject传入参数,给下一个函数或者Promise传入初始值。

    4. 已拒绝的Promise,可以通过.catch或者.then的第二个参数或者try catch进行捕获。

    封装异步操作为Promise

    我们可以将任何接受回调的函数封装成一个Promise,例如封装第一个函数:

    // 原函数
    function syncFunc(cb) {
        setTimeout(function() {
            cb();
        }, 1000);
    }
    var callback = function() {
        console.log('success');
    }
    syncFunc(callback);
    
    // 封装之后
    function syncFunc() {
        return new Promise(function(resolve, reject) {
            setTimeout(function() {
                resolve();
            }, 1000);
        });
    }
    var callback = function() {
        console.log('success');
    }
    
    syncFunc().then(callback);

    小结:

    1. 我们可以轻松的吧任何一个函数或者异步的函数改为Promise,尤其是异步函数,改为Promise之后可以进行链式调用。
    2. 将带有回调函数的异步改为Promise也很简单,只需要在内部实例化Promise之后,在原理执行回调的地方执行对应更改Promise转态的函数即可。
  • 相关阅读:
    员工管理,这么做就对了
    学会自我管理的好处及自我管理包括的内容
    职场人必看的5本书推荐,首推《情商必读12篇》
    企业管理方面的经典著作推荐
    这6本精心挑选的团队管理类好书助你做好团队管理
    战略规划,你的企业真的做对了吗?
    如何提高说服力?说服的技巧有哪些?这本书能给你答案
    读书使人进步,这本营销书籍让你真正读懂市场营销
    P1228 地毯填补问题题解
    P1010 幂次方题解
  • 原文地址:https://www.cnblogs.com/shenjp/p/12482754.html
Copyright © 2011-2022 走看看