promise异步编程介绍

promise异步编程介绍

Promise 是什么?

Promise 对象用来进行延迟(deferred) 和 异步(asynchronous) 计算。

解决的问题

回调函数是JavaScript的一大特色! node.js官方的api基本都是以会回调方式传递函数返回值。习惯同步编程的对这种异步方式多少会产生水土不服,而且层层嵌套,不知不觉就建造起了一座高高的回调金字塔。针对这种普遍问题,Promise应势而生!

我们举个例子

有以下的业务场景,从服务器中,依次请求三张图片,每次有一张图片加载完成,就打印结果。

一般正常的写法

    /**
     * [loadimg 加载一张图片]
     * @param  {[type]}   url      [description]
     * @param  {Function} callback [description]
     * @return {[type]}            [description]
     */
    function loadimg(url, callback) {
        var img = new Image();
        img.src = url;
        img.onload = callback;
    }

    //开始加载图片
    loadimg("img/a.png", function() {
        console.log("图片a已经加载完毕");
        loadimg("img/b.png", function() {
            console.log("图片b已经加载完毕");
            loadimg("img/c.png", function() {
                console.log("图片c已经加载完毕");
                console.log("a,b,c三张图片已经完全加载完毕");
            });
        });
    });

ps:是不是很恐怖

采用promise的写法

    /**
     * [loadimg 加载一张图片]
     * @param  {[type]}   url      [description]
     * @param  {Function} callback [description]
     * @return {[type]}            [description]
     */
    function loadimg(url) {
        return new Promise(function(resolve, reject) {
            var img = new Image();
            img.src = url;
            img.onload = function() {
                resolve();
            };
        });
    }
    //开始加载图片
    loadimg("img/a.png").then(function() {
        console.log("图片a已经加载完毕");
        return loadimg("img/b.png");
    }).then(function() {
        console.log("图片b已经加载完毕");
        return loadimg("img/c.png");
    }).then(function() {
        console.log("图片c已经加载完毕");
        console.log("a,b,c三张图片已经完全加载完毕");
    });
基本用法(then方法)
Promise/A+规范
  • 一个promise可能有三种状态:等待(pending)、已完成(fulfilled)、已拒绝(rejected)
  • 一个promise的状态只可能从“等待”转到“完成”态或者“拒绝”态,不能逆向转换,同时“完成”态和“拒绝”态不能相互转换
  • Promise构造函数接受一个函数作为参数,该函数的两个参数分别是resolve方法和reject方法。如果异步操作成功,则用resolve方法将Promise对象的状态变为“成功”(即从pending变为resolved);如果异步操作失败,则用reject方法将状态变为“失败”(即从pending变为rejected)。
  • promise必须实现then方法(可以说,then就是promise的核心),而且then必须返回一个promise,同一个promise的then可以调用多次,并且回调的执行顺序跟它们被定义时的顺序一致
  • then方法接受两个参数,第一个参数是成功时的回调,在promise由“等待”态转换到“完成”态时调用,另一个是失败时的回调,在promise由“等待”态转换到“拒绝”态时调用。同时,then可以接受另一个promise传入,也接受一个“类then”的对象或方法,即thenable对象。

创建Promise

    var promise = new Promise(function(resolve, reject) {
        // 做一些异步操作的事情,在这里做了一个定时时间为1000ms的定时器任务
        setTimeout(function() {
            if ( /* 一切正常 */ false) {
                resolve("promise worked!");
            } else {
                reject("promise failed");
            }
        }, 1000);
    });

Promise 的构造器接受一个函数作为参数,它会传递给这个回调函数两个变量 resolve 和 reject。在回调函数中做一些异步操作

成功之后调用对象的then方法,该方法中有两个参数 1. resolve(val), val的返回成功的参数

否则调用 2.reject() //处理业务错误时的函数

获取异步完成后的参数

  promise.then(function(val) {
        // success
        console.log(val);
    }, function(val) {
        // failure
        console.log(val);
    });
promise catch 方法

catch 方法是 then(null,reject)中的reject处理的替代方法,用于指定发生错误时的回调函数

ps: promise对象的错误具有冒泡性质,会一直向后传递,直到被捕获为止

在这个例子中,创建一个Promise 发出一个异常消息

    var promise = new Promise(function(resolve, reject) {
        // resolve("ok");
        reject("false");  //发出一个错误的异常消息
    });

在这里我们使用catch来捕获错误

    promise.then(function(str){
       console.log("正确结果"+str);
    }).catch(function(str){
      console.log("异常结果"+str);
    });

在这里我们使用then(null,reject) 中的reject来捕获错误

    promise.then(function(str) {
        console.log("正确结果" + str);
    }, function(str) {
        console.log("异常结果" + str);
    });
all方法

Promise.all方法接受一个数组作为参数,p1、p2、p3都是Promise对象的实例。(Promise.all方法的参数不一定是数组,但是必须具有iterator接口(可遍历对象接口),且返回的每个成员都是Promise实例。)

p的状态由p1、p2、p3决定,分成两种情况。

(1)只有p1、p2、p3的状态都变成fulfilled,p的状态才会变成fulfilled,此时p1、p2、p3的返回值组成一个数组,传递给p的回调函数。

(2)只要p1、p2、p3之中有一个被rejected,p的状态就变成rejected,此时第一个被reject的实例的返回值,会传递给p的回调函数。

    /**
     * [createPromise 创建一个promise对象]
     * @param  {[type]} str [description]
     * @return {[type]}     [description]
     */
    function createPromise(str) {
        return new Promise(function(resolve, reject) {
            setTimeout(function() {
                if (true) {
                    resolve(str); //返回标志位
                } else {
                    reject();
                }
            }, 1000);
        });
    }

    var promise1 = createPromise("p1"),
        promise2 = createPromise("p2"),
        promise3 = createPromise("p3");
    //通过all方法将三个promise实例包装成新的promise实例
    var promise = Promise.all([promise1, promise2, promise3]);
    promise.then(function(results) {
        console.log(results); // ["p1", "p2", "p3"]
    });
race方法

只要p1、p2、p3之中有一个实例率先改变状态,p的状态就跟着改变。那个率先改变的Promise实例的返回值,就传递给p的返回值。

    /**
     * [createPromise 创建一个promise对象,通过传入不同的时间,来区别回调的时间]
     * @param  {[type]} str    [description]
     * @param  {[type]} second [description]
     * @return {[type]}        [description]
     */
    function createPromise(str, second) {
        return new Promise(function(resolve, reject) {
            setTimeout(function() {
                if (true) {
                    resolve(str); //返回标志位
                } else {
                    reject();
                }
            }, second);
        });
    }

    var promise1 = createPromise("p1", 5000),
        promise2 = createPromise("p2", 1000),
        promise3 = createPromise("p3", 2000);
    //通过race方法将三个promise实例包装成新的promise实例
    var promise = Promise.race([promise1, promise2, promise3]);
    promise.then(function(results) {
        console.log(results); // "p2"
    });
Promise.resolve方法 Promise.reject方法

有时需要将现有对象转为Promise对象,我们可以这样做

var p = Promise.resolve('this is promise');

下面的代码生成一个新的Promise对象的实例p,它的状态为fulfilled/rejected,所以回调函数会立即执行,Promise.resolve方法的参数就是回调函数的参数。

如果Promise.resolve方法的参数是一个Promise对象的实例,则会被原封不动地返回。

Promise.reject(reason)方法也会返回一个新的Promise实例,该实例的状态为rejected。Promise.reject方法的参数reason,会被传递给实例的回调函数。

    var p = Promise.resolve('this is promise');
    var p = Promise.reject('the promise is error');

    p.then(function(result) {
        console.log(result); //捕获正常结果
    }).catch(function(result) {
        console.log(result); //捕获错误结果
    });
兼容不支持promise的环境

在html中引入

<script src="https://www.promisejs.org/polyfills/promise-7.0.4.min.js"></script>
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值