JavaScript 中的 Promise 机制

阅读 686
收藏 50
2016-12-22
原文链接:blog.csdn.net

1.前言:

如我们所知道的javascript是一门单线程语言,不像java语言中有多线程的机制,前不久做项目的时候,需要在前端使用js进行一些列的ajax异步请求,这些请求之间有一种关系,就是下一次请求的参数是上一次请求的结果,在javaweb端我们可以很容易的用同步请求的方式解决,阻塞线程知道函数执行完,但是在前端的ajax中就得不断的嵌套函数,十分的恶心,好在最后找到了Promise这个好东西,并将学习成果总结下来。

2.Promise:

2.1:Promise 的resolve 和reject

就如其名一样,Promise类似于某种承诺,当我们在特定的时候告诉它应该干什么(异步请求成功后),它就会在接受到结果后第一时间告诉我们,类似于java中的回调函数,而且它可以使用一种链式的结构,将我们的异步请求连接起来,只有当我们前面的异步请求成功后,后面的异步函数才会执行。

举个栗子:

这里写图片描述

这里我们简单的模拟了一个异步请求,在两秒后我们可以看到alert显示了我们的信息,这看起来貌似没有什么蛋用啊,可是这只是一个简单的演示,如果我们的异步请求多了就可以看出它的威力了,解析来我们就来一个三个异步的栗子:

这里写图片描述

上面的代码看起来有点乱啊,其实就是三个延迟函数而已,我们可以在控制台上看见间隔2秒、1秒、1秒后我们的结果按顺序的打印出来了,实际情况中我们并不会这样写,这样多来几次有懵逼了,我们最终的代码会像如下这样:

    第一个异步请求的: promise.then(function(result){
                    return promise2;
                }).then(function(result2){
                    reutrn promise3;
                })...//N个一条链式的结构

那这就有一个疑问了,网络请求不都是成功的,可能是失败的,我们不希望在请求失败后依然去调用下一个请求,这是我们就需要Promise函数的第二个方法了,Promise.reject();用法和第一个成功回调一样,唯一的区别是回调的函数有一点差异,下面就举一个栗子:

这里写图片描述

这里我们定义了一个假的异步请求,我们随机一个返回值,如果大于5,我们就认为成功,alert success回调,如果失败就在控制台打印。大家就发现了,then()函数的第二个参数就是失败的回调,一个promise要么成功要么失败。

以上就是Promise的简单使用,我们再来看几个高级一点的例子:

假设有如下场景,我们查询两种分开的表,前一张表的结果是后一张表的参数,而且后一次查询还不止一次,打个比方:我们去买苹果,买苹果就是我们的第一个请求,但是有很多种的苹果,我们为了确定哪个好吃我们需要每种都试吃一遍,然后选择一种,当然如果在现实中,可能我们这样做草都一米高了。这时候前面的方法就不适用了,我们需要一个新的方法。

2.2 Promise的all:

Promise.all()函数就是一个解决上诉问题的方法,它接受一个promise的数组,当这些promise都执行完后或则有一个失败的时候回调。

这里写图片描述

我们定义两个成功的回调,在两个异步执行完成之后,我们会得到一个保存结果的数组,结果数组中的结果与之前的参数的promise对应,就是p3的结果是result[0],依次类推。

那么在如果我们的异步请求中如果有一个出错的会怎么样了?

这里写图片描述

我们将上诉方法稍微改造下,让第二个异步失败,此时我们可以在控制台上输出了four error,并没有three的影子,这就是all的特点,要么全部成功,要么在第一个error出停止。我们接着看下一个函数。

2.3 Promise的race:

这个方法比较有意思,Promise.race(),这个方法也是接受一个promise数组作为参数,返回一个promise,但是它就如它的名字一样,他只返回最先执行完的第一个promise的结果。

2.4Promise的catch:

在上面我们说了promise可以将一系列的异步请求串起来,此时就有一个问题,如果我们不想在每个异步请求的回调里去检测失败,只关心最终的结果,此时我们就可以使用catch()函数,它可以捕获我们执行调用链中的reject和exception,写法如下:

    promise.then(function(){
        return promise;
    }).then(function(){
        //do something
    }).catch(function(error){

    })

这里需要注意的就是,当我们回调链中有一个函数接受了错误的回调,那么catch函数就不会被调用了。以上就是javascript自带的Promise,下面我们看一个Angular1.x中的Promise机制。

3.Angular中的$q

在Angular1.x中我们可以在controller中注入$q使用Promise函数下面就简单介绍一下。

    //声明一个模块
    var app=angular.module('appM',[]);
    //定义一个控制器并注入我们的$scope和$q
    app.controller('myCtrl',['$scope','$q',function($scope,$q){
        //定义一个异步请求方法:
        $scope.httpRequest=function(param){
            var defer=$q.defer();
            //异步操作
            if(suc){
                defer.resolve();
            }else{
                defer.reject();
            }

            return defer.promise;
        }

        $scope.httpRequest().then(function(suc){
            //成功
        },function(er){
            //失败
        })

    }])

Angular中的$q还有

  1. when():一般在参数不确定的时候使用
  2. all():和javascript中的效果一样
  3. finally():类似于java中的try catch最后的finally方法。

本文对你有帮助?欢迎扫码加入前端学习小组微信群:

评论