美文网首页
ES6 promise 解惑

ES6 promise 解惑

作者: kuohao | 来源:发表于2017-03-10 15:59 被阅读62次

    promise 的由来

    有时候我们做ajax请求,可能会遇到以下这种情况
    requsetA > requsetB > requestC
    requestB的请求依赖requestA的数据,requestC的请求依赖requestB的数据。在没有异步编程的概念那时,我们往往只能通过回调函数的方法去解决这个问题。

         requestA(function(res){
                requestB(function(res){
                      requestC(function(res){
                            //do something
                      })
                })
          })
    

    其实也不是很难看,比较有层次感,哈哈。。。

    然而,实际情况并不会想现在那样那么简单,你可能还需要将requestA的数据进行一些处理才能够传给requestB,requestB请求回来的数据,又得做一些处理才能传给requestC,那么这就会变成一团巨大的函数体,可读性十分糟糕。

    所以就有了promise对象的出现,它是专治多重依赖的异步操作的。

    我们可以使用promise来改写以上代码

    promise走起

    //定义 一个promise对象,进行requestA异步请求
      let pro = new Promise((resolve,reject)=>{
           requestA({//一些配置})
           //jquery 1.8+ 新写法,success已经过时
          .done((data)=>{
              //resolve方法将参数传递给下一个回调函数
              resolve(data)  
          })
          .error((err)=>{
              reject(err);  
          })
      })
    
     //进行requestB异步请求
    let requestB = (res)=>{
        let pro1 = new Promise((resolve,reject)=>{
          reqb({//一些配置})
          .done((data)=>{
                console.log(res);
                resolve(data);
          })
          .error((err)=>{
              reject(err);  
          })
      })
    
     //进行requestC异步请求
    let requestC = (res)=>{
        let pro2 = new Promise((resolve,reject)=>{
          reqc({//一些配置})
          .done((data)=>{
                console.log(res);
                console.log(data);
          })
          .error((err)=>{
              reject(err);  
          })
      })
    
    //然后 ,使用优雅的方式进行异步回调
    
    pro.then(requestB)
       .then(requestC)
    

    promise与传统的ajxa同步请求

    让我们先来做一个实验

    1. 写段简单的服务端代码,以php为例
       <?php
          //睡眠5秒,模拟真实网络请求环境
           sleep(5);
          //防止跨域请求
           header('Access-Control-Allow-Origin:*');
           header('Access-Control-Allow-Methods:POST,GET');
            //获取前端get请求参数,返回
           $usript = $_GET['keyword'];
           echo $usript;
       ?>
    
    1. 封装原生ajax请求
    //使用 ES6赋值解构语法
     function ajax({url,test,bool,callback}){
                var ajax = new XMLHttpRequest();
                ajax.onreadystatechange = function() {
                    if (ajax.readyState == 4 && ajax.status == 200) {
                        var response = ajax.responseText;
                        Object.prototype.toString.call(callback) === '[object Function]' && callback(response)
                        test && console.timeEnd(test)
                    }
                };
                ajax.open("GET", url, bool);
                ajax.setRequestHeader("Content-type", "text/plain");
                ajax.send();
            }
    
    1. 编写同步测试代码
    //使用chrome控制台api 的console.time()进行计时操作
    ajax({
                url:"http://192.168.1.105/index.php?keyword=123",
                bool:false,
                callback:(res)=>{
                    ajax({
                        url:"http://192.168.1.105/index.php?keyword=123",
                        test:'sync test',
                        bool:false,
                        callback:(data) => console.log(`${res} -requestA: ${data}`)
                    })
                }
            })
    console.log('hello promise')
    

    结果

    123
    test.html:15 sync test: 10014.349ms
    hello promise
    

    结果显而易见ajax同步请求会阻塞javascript运行,导致其后的代码阻塞等待,严重拖低性能

    1. 编写异步测试代码
       console.time('async test')
            let pro = new Promise((resolve,reject)=>{
                ajax({
                    url:"http://192.168.1.105/index.php?keyword=123",
                    bool:true,
                    callback:(data)=>{
                        if(data){
                            resolve(data);
                        }else{
                            reject('请求错误!')
                        }
                    }
                })
            })
    
            let requestA = (res)=>{
                let resA = new Promise((resolve,reject)=>{
                ajax({
                    url:"http://192.168.1.105/index.php?keyword=123",
                    bool:true,
                    callback:(data)=>{
                        if(data){
                            console.log(`${res} -requestA: ${data}`)
                        }else{
                            reject('请求错误!')
                        }
                    },
                    test:'async test'
                })
            })
        }
        pro.then(requestA);
    
        console.log('hello promise')
    

    结果

    hello promise
    test.html:62 123 -requestA: 123
    test.html:15 async test: 10022.117ms
    

    promise是异步的,引擎执行代码的时候会先将异步代码挂起,先去执行其他代码,等待上一个请求结束再回过头来执行下一个请求的代码,所以,虽然promise和ajax同步请求用的时间一样多,也可以说promise就是在做同步请求,但是promise本身是异步的,并不会阻塞代码,所以你可以看到先打印出了hello promise

    相关文章

      网友评论

          本文标题:ES6 promise 解惑

          本文链接:https://www.haomeiwen.com/subject/ofingttx.html