ES6-Promise与Generator结合

时间:2021-03-25 23:30:43

需求:使用ajar依次发送3次网络请求, 必须前一次发送成功后才能进行下一次的网络请求。

目的:实现把异步代码的风格写成了同步代码的风格。这个就是Promise + Generator 结合的精髓

1.jQuery中ajar的实现

使用ajar依次发送3次网络请求, 第一次请求user.json, 请求成功后发起第二次网络请求获取banners.json , 第二次获取banners.json成功后接着继续发送第三次网络请求获取goods.json

在进入主题之前先回顾一下jQuery中ajar的实现过程

<script src="jquery-1.11.3.min.js"></script>
    <script> /*1.第一次*/ $.ajax({ url:'user.json', dataType:'json', success:function (res1) { /*2.第二次*/ console.log(res1); $.ajax({ url:'banners.json', dataType:'json', success:function (res2) { /*3.第三次*/ console.log(res2); $.ajax({ url:'goods.json', dataType:'json', success:function (res3) { console.log(res3); }, error:function (error) { console.log(error); } }) }, error:function (error) { console.log(error); } }) }, error:function (error) { console.log(error); } }) </script>

2.Promise + ajar 实现

在回顾一下Promise + ajar的实现过程

 <script src="jquery-1.11.3.min.js"></script>
    <script> /*1.第一次*/ var promise1=new Promise(function (resolve,reject) { $.ajax({ url:'user.json', dataType:'json', success:function (res1) { resolve(res1) }, error:function (error) { reject(error) } }) }) /*2.第二次*/ var promise2=new Promise(function (resolve,reject) { $.ajax({ url:'banners.json', dataType:'json', success:function (res2) { resolve(res2) }, error:function (error) { reject(error) } }) }) /*3.第二次*/ var promise3=new Promise(function (resolve,reject) { $.ajax({ url:'goods.json', dataType:'json', success:function (res3) { resolve(res3) }, error:function (error) { reject(error) } }) }) /*1.第一次*/ promise1.then( function (res1) { console.log(res1); /*2.第二次*/ promise2.then( function (res2) { console.log(res2); /*3.第三次*/ promise3.then( function (res3) { console.log(res3); }, function (error) { }) }, function (error) { }) }, function (error) { }) </script>

对上面的代码的简写:

 <script src="jquery-1.11.3.min.js"></script>
    <script> /*1.第一次*/ Promise.all([ $.ajax({url:'user.json',dataType:'json',}) ]).then( function (res1) { console.log(res1); /*2.第二次*/ Promise.all([ $.ajax({url:'banners.json',dataType:'json',}) ]).then( function (res2) { console.log(res2); /*3.第三次*/ Promise.all([ $.ajax({url:'goods.json',dataType:'json',}) ]).then( function (res3) { console.log(res3); }, function (error) { }) }, function (error) { }) }, function (error) { }) </script>

上面的代码虽然可以实现,但是没有实现把异步代码的风格写成了同步代码的风格。异步还是通过回调,回调,回调的方式。下面正式进入主题。

3. Promise + Generator + ajar 实现

正式进入主题:用Promise + Generator + ajar 实现上面的需求

 <script src="jquery-1.11.3.min.js"></script>
    <script>
        /** * 1.定义一个generator函数 *myFetchs * */
       function *myFetchs() {
           /** * 1.1第一次网络请求 * $.ajax({url:'user.json',dataType:'json'}) : 作为第一次调用next的返回值,是promise对象 * promise1 : 第二次调用next函数中的参数 */
           var promise1=yield $.ajax({url:'user.json',dataType:'json'});
           /** * 1.2第二次网络请求 * $.ajax({url:'user.json',dataType:'json'}) : 作为第二次调用next的返回值,是promise对象 * promise2 : 第三次调用next函数中的参数 */
           var promise2=yield $.ajax({url:'banners.json',dataType:'json'});
           /** * 1.3 第三次网络请求 * return promise3 : 作为第三次调用next的返回值,是promise对象 */
           var promise3=$.ajax({url:'goods.json',dataType:'json'});
           return promise3;
       }

        /** * 2.获取generatorObj对象(迭代器对象) */
        var generatorObj=myFetchs();


        /**3.开始执行*myFetch函数*/
        /*3.1发起第一次网络请求*/
        var result1=generatorObj.next();  //第一次调用next函数
        var promise1=result1.value;
        promise1.then(
            //如果第一次请求成功
            function (res1) {
                console.log(res1);
                /*3.2发起第二次网络请求*/
                var result2=generatorObj.next('promise1='+res1);  //第二次调用next函数
                var promise2=result2.value;
                promise2.then(function (res2) {
                    console.log(res2);
                    /*3.3发起第三次网络请求*/
                    var result3=generatorObj.next('promise2='+res1); //第三次调用next函数
                    var promise3=result3.value;
                    promise3.then(function (res3) {
                        console.log(res3);
                    },function (error) {

                    })
                },function (error) {

                })
            },
            function (error) {

            })

    </script>

上面的代码已经实现上面所说的需求,但是代码还是比较复杂。为了简化代码,接下来抽取并封装一下代码

把上面的代码封装一下:

封装后的代码如下,这下发起3次网路请求的代码看起来精简了很多,

并且这里已经实现把异步代码的风格写成同步代码的风格

这个就是Promise + Generator 结合的精髓

        /** * 依次发起3次网络请求精简版 * */
        runGeneratorFunction(function *() {
            //发送第一次网络请求
            var promise1=yield $.ajax({url:'user.json',dataType:'json'});
            //发送第二次网络请求
            var promise2=yield $.ajax({url:'banners.json',dataType:'json'});
            //发送第三次网络请求
            var promise3=$.ajax({url:'goods.json',dataType:'json'});
            return promise3;
        })

其中runGeneratorFunction函数的简单实现

       /** * 负债运行Generator函数,参数是一个Generator函数 */
        function runGeneratorFunction(genFunction) {
            /** * 2.获取generatorObj对象(迭代器对象) */
            var generatorObj=genFunction();


            /**3.开始执行*myFetch函数*/
            /*3.1发起第一次网络请求*/
            var result1=generatorObj.next();  //第一次调用next函数
            var promise1=result1.value;
            promise1.then(
                //如果第一次请求成功
                function (res1) {
                    console.log(res1);
                    /*3.2发起第二次网络请求*/
                    var result2=generatorObj.next('promise1='+res1);  //第二次调用next函数
                    var promise2=result2.value;
                    promise2.then(function (res2) {
                        console.log(res2);
                        /*3.3发起第三次网络请求*/
                        var result3=generatorObj.next('promise2='+res2); //第三次调用next函数
                        var promise3=result3.value;
                        promise3.then(function (res3) {
                            console.log(res3);
                        },function (error) {

                        })
                    },function (error) {

                    })
                },
                function (error) {

                })
        }

专门用来运行Generator函数的插件已经存在,不用自己再重复封装一个