美文网首页前端开发
利用Promise知识,用原生JS封装Ajax

利用Promise知识,用原生JS封装Ajax

作者: 番茄沙司a | 来源:发表于2018-10-14 00:24 被阅读27次

    Promise

    1. Promise特点

    • 承诺将来会执行
    • 防止回调地狱 - Callback Hell
    • 可以进行then的链式执行
    • 区分数据请求和数据处理
    • 三种状态
      • pending:等待中,或者进行中,表示还没有得到结果
      • resolved(fullfilled):已经完成,表示得到了我们想要的结果,可以继续往下执行
      • rejected:也表示得到结果,但是由于结果并非我们所愿,因此拒绝执行
    • 调用时会被传递两个参数:resolvereject函数

    利用Promise知识,用原生JS封装AJAX

    var url = 'https://请求的路径';
    
    // 封装一个get请求的方法
    function getJSON(url) {
      return new Promise(function (resolve, reject) {
        var XHR = new XMLHttpRequest();
    
        XHR.onreadystatechange = function () {
          //readyState属性表示请求/响应过程的当前活动阶段。
          if (XHR.readyState == 4) {
            if ((XHR.status >= 200 && XHR.status < 300) || XHR.status == 304) {
              try {
                var response = JSON.parse(XHR.responseText);
                resolve(response);
              } catch (e) {
                reject(e);
              }
            } else {
              reject(new Error("Request was unsuccessful: " + XHR.status));
            }
          }
        }
        XHR.open('GET', url, true);
        XHR.send(null);
      })
    }
    
    getJSON(url).then(resp => console.log(resp));
    

    readyState
    0 - 代表未初始化。 还没有调用 open 方法
    1 - 代表正在加载。 open 方法已被调用,但 send 方法还没有被调用
    2 - 代表已加载完毕。send 已被调用。请求已经开始
    3 - 代表交互中。服务器正在解析响应内容
    4 - 代表完成。响应发送完毕

    2. Promise 语法

    以异步操作img为例

    2.1 ES5 异步Callback实现

    function loadImg(src, callback, fail) {
        var img = document.createElement('img')
        img.onload = function () {
            callback(img)
        }
        img.onerror = function () {
            fail()
        }
        img.src = src
    }
    var src = 'https://img.mukewang.com/5be2bcb30001a46709360316.jpg'
    loadImg(src, function (img) {
        console.log(img.width)
    }, function () {
        console.log('failed')
    })
    

    2.2 Promise实现

    function loadImg(src) {
        const promise = new Promise(function (resolve, resolve) {
            var img = document.createElement('img')
            img.onload = function () {
                resolve(img)
            }
            img.onerror = function () {
                reject()
            }
            img.src = src
        })
        return promise
    }
    
    
    var src = 'https://img.mukewang.com/5be2bcb30001a46709360316.jpg'
    var result = loadImg(src)
    
    result.then(function (img) {
        console.log(img.width)
    }, function () {
        console.log('failed')
    })
    result.then(function (img) {
        console.log(img.height)
    })
    

    优点:便于集成、扩展
    注意:

    • new Promise 实例,必须要 return
    • new Promise 时要传入函数,函数有 resolve reject 两个参数
    • 成功时执行 resolve() 失败时执行 reject()

    2.3 重要语法

    • Promise.all接收一个Promise对象组成的数组作为参数,当这个数组所有的Promise对象状态都变成resolved或者rejected的时候,它才会去调用then方法。

    • Promise.race与Promise.all相似的是,Promise.race都是以一个Promise对象组成的数组作为参数,不同的是,只要当数组中的其中一个Promsie状态变成resolved或者rejected时,就可以调用.then方法了。

    • 如何有效的将ajax的数据请求和数据处理分别放在不同的模块中进行管理

      • 将所有的数据请求这个动作放在同一个模块中统一管理
      define(function(require) {
          var API = require('API');
      
          // 因为jQuery中的get方法也是通过Promise进行了封装,最终返回的是一个Promise对象,因此这样我们就可以将数据请求与数据处理放在不同的模块,即使用一个统一的模块来管理所有的数据请求
      
          // 获取当天的信息
          getDayInfo = function() {
              return $.get(API.dayInfo);
          }
      
          // 获取type信息
          getTypeInfo = function() {
              return $.get(API.typeInfo);
          };
      
          return {
              getDayInfo: getDayInfo,
              getTypeInfo: getTypeInfo
          }
      });
      

      可以增加过滤处理

      • 拿到数据并处理数据
      // components/calendar.js
      define(function(require) {
          var request = require('request');
      
          // 拿到数据之后,需要处理的组件,可以根据数据渲染出需求想要的样式
      
          request.getTypeInfo()
              .then(function(resp) {
      
                  // 拿到数据,并执行处理操作
                  console.log(resp);
              })
      
          // 这样,我们就把请求数据,与处理数据分离开来,维护起来就更加方便了,代码结构也足够清晰
      })
      

    相关文章

      网友评论

      本文标题:利用Promise知识,用原生JS封装Ajax

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