javascript Promise簡單學(xué)習(xí)使用方法小結(jié)

字號:


    下面小編就為大家?guī)硪黄猨avascript Promise簡單學(xué)習(xí)使用方法小結(jié)。小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。
    解決回調(diào)函數(shù)嵌套太深,并行邏輯必須串行執(zhí)行,一個Promise代表一個異步操作的最終結(jié)果,跟Promise交互的主要方式是通過他的then()方法來注冊回調(diào)函數(shù),去接收Promise的最終結(jié)果值
    Promise相關(guān)的協(xié)議有PromiseA和PromiseA+
    定義一個類Promise
    定義屬性隊列queue,初始化空數(shù)組[]
    定義屬性值value,初始化null
    定義屬性狀態(tài)status,初始化“pending”(默認(rèn)值)
    定義成員方法getQueue(),返回屬性queue
    定義成員方法getStatus(),返回屬性status
    定義成員方法setStatus(),設(shè)置狀態(tài),傳遞參數(shù):status,value
    判斷status為fulfilled或者rejected,
    設(shè)置status屬性this.status=status
    設(shè)置value屬性this.value=value || null ,如果不傳value就是null
    定義凍結(jié)變量freezeObject
    定義成員方法isFulfilled(),判斷當(dāng)前狀態(tài)是否是(完成)
    定義成員方法isRejected(),判斷當(dāng)前狀態(tài)是否是(失?。?BR>    定義成員方法isPending(),判斷當(dāng)前狀態(tài)師傅是(等待)
    定義成員方法then(),傳遞參數(shù):onFulfilled成功的回調(diào),onRejected失敗的回調(diào)
    定義對象handler對象,屬性fulfilled,rejected兩個回調(diào)函數(shù)
    定義handler對象的deferred屬性,Deferred對象
    判斷當(dāng)前狀態(tài)是否等待,如果是等待 把handler對象塞入queue隊列數(shù)組
    如果不是等待狀態(tài),調(diào)用Utils對象的procedure()方法,參數(shù):status,
    返回 handler.deferred.promise對象
    定義一個類Deferred
    定義屬性promise,初始化Promise對象
    定義成員方法resolve(),傳遞參數(shù):result結(jié)果
    判斷Promise對象的狀態(tài)是 等待,直接返回
    調(diào)用Promise對象的getQueue()方法,獲取queue數(shù)組
    循環(huán)數(shù)組
    //todo調(diào)用工具類Utils. procedure()方法,參數(shù):“fulfilled”,元素,err信息
    調(diào)用Promise對象的setStatus()方法,設(shè)置狀態(tài),參數(shù):'fulfilled',result
    定義成員方法reject,傳遞參數(shù):err錯誤信息
    判斷Promise對象的狀態(tài)是 等待,直接返回
    調(diào)用Promise對象的getQueue()方法,獲取queue數(shù)組
    循環(huán)數(shù)組
    //todo,調(diào)用工具類Utils. procedure()方法,參數(shù):“rejected”,元素,err信息
    調(diào)用Promise對象的setStatus()方法,設(shè)置狀態(tài),參數(shù):'fulfilled',result
    定義工具類Utils,使用匿名函數(shù)立即執(zhí)行,得到一個對象
    返回對象,對象中有一個方法procedure()
    定義procedure()方法,傳遞參數(shù):type狀態(tài)類型,handler處理器數(shù)組,result結(jié)果
    獲取到處理函數(shù)func,在handler[type]
    到這里我看暈了。。。
    使用方法:
    定義一個函數(shù)ajax,傳遞參數(shù):url路徑
    獲取Deferred對象,new出來
    ajax請求數(shù)據(jù)的代碼,在返回數(shù)據(jù)的回調(diào)方法中
    如果成功了調(diào)用Deferred對象的resolve()方法,參數(shù):返回的數(shù)據(jù)
    如果失敗了調(diào)用Deferred對象的reject()方法,參數(shù):返回的數(shù)據(jù)
    返回Deferred.promise對象
    調(diào)用ajax()方法,得到promise對象,參數(shù):url,
    調(diào)用promise對象的then()方法,參數(shù):匿名函數(shù)
    調(diào)用ajax()方法,獲取到promise對象,返回這個對象
    形成鏈?zhǔn)秸{(diào)用
    js部分:
    <script>
    //Promise代碼部分(我選擇狗帶)
    Promise = function() {
      this.queue = [];
      this.value = null;
      this.status = 'pending';// pending fulfilled rejected
    };
    Promise.prototype.getQueue = function() {
      return this.queue;
    };
    Promise.prototype.getStatus = function() {
      return this.status;
    };
    Promise.prototype.setStatus = function(s, value) {
      if (s === 'fulfilled' || s === 'rejected') {
        this.status = s;
        this.value = value || null;
        this.queue = [];
        var freezeObject = Object.freeze || function(){};
        freezeObject(this);// promise的狀態(tài)是不可逆的
      } else {
        throw new Error({
          message: "doesn't support status: " + s
        });
      }
    };
    Promise.prototype.isFulfilled = function() {
      return this.status === 'fulfilled';
    };
    Promise.prototype.isRejected = function() {
      return this.status === 'rejected';
    }
    Promise.prototype.isPending = function() {
      return this.status === 'pending';
    }
    Promise.prototype.then = function(onFulfilled, onRejected) {
      var handler = {
        'fulfilled': onFulfilled,
        'rejected': onRejected
      };
      handler.deferred = new Deferred();
      if (!this.isPending()) {//這里允許先改變promise狀態(tài)后添加回調(diào)
        utils.procedure(this.status, handler, this.value);
      } else {
        this.queue.push(handler);//then may be called multiple times on the same promise;規(guī)范2.2.6
      }
      return handler.deferred.promise;//then must return a promise;規(guī)范2.2.7
    };
    var utils = (function(){
      var makeSignaler = function(deferred, type) {
        return function(result) {
          transition(deferred, type, result);
        }
      };
      var procedure = function(type, handler, result) {
        var func = handler[type];
        var def = handler.deferred;
        if (func) {
          try {
            var newResult = func(result);
            if (newResult && typeof newResult.then === 'function') {//thenable
              // 此種寫法存在閉包容易造成內(nèi)存泄露,我們通過高階函數(shù)解決
              // newResult.then(function(data) {
              //   def.resolve(data);
              // }, function(err) {
              //   def.reject(err);
              // });
              //PromiseA+規(guī)范,x代表newResult,promise代表def.promise
              //If x is a promise, adopt its state [3.4]:
              //If x is pending, promise must remain pending until x is fulfilled or rejected.
              //If/when x is fulfilled, fulfill promise with the same value.
              //If/when x is rejected, reject promise with the same reason.
              newResult.then(makeSignaler(def, 'fulfilled'), makeSignaler(def, 'rejected'));//此處的本質(zhì)是利用了異步閉包
            } else {
              transition(def, type, newResult);
            }
          } catch(err) {
            transition(def, 'rejected', err);
          }
        } else {
          transition(def, type, result);
        }
      };
      var transition = function(deferred, type, result) {
        if (type === 'fulfilled') {
          deferred.resolve(result);
        } else if (type === 'rejected') {
          deferred.reject(result);
        } else if (type !== 'pending') {
          throw new Error({
            'message': "doesn't support type: " + type
          });
        }
      };
      return {
        'procedure': procedure
      }
    })();
    Deferred = function() {
      this.promise = new Promise();
    };
    Deferred.prototype.resolve = function(result) {
      if (!this.promise.isPending()) {
        return;
      }
      var queue = this.promise.getQueue();
      for (var i = 0, len = queue.length; i < len; i++) {
        utils.procedure('fulfilled', queue[i], result);
      }
      this.promise.setStatus('fulfilled', result);
    };
    Deferred.prototype.reject = function(err) {
      if (!this.promise.isPending()) {
        return;
      }
      var queue = this.promise.getQueue();
      for (var i = 0, len = queue.length; i < len; i++) {
        utils.procedure('rejected', queue[i], err);
      }
      this.promise.setStatus('rejected', err);
    }
    /*****************************上面看不懂,分割線************************************/
    //測試部分
    ajax = function(url) {
      var def = new Deferred();
      var xhr = new XMLHttpRequest();
      xhr.onreadystatechange = function() {
        if (xhr.readyState === 4) {
          if ((xhr.status >=200 && xhr.status < 300) || xhr.status === 304) {
            def.resolve(xhr.responseText)
          } else {//簡化ajax,沒有提供錯誤回調(diào)
            def.reject(new Error({
              message: xhr.status
            }));
          }
        }
      };
      xhr.open('get', url, true);
      xhr.send(null);
      return def.promise;
    }
    ajax('test.php?act=1').then(function(data1) {
      console.log(data1);//處理data1
      return ajax('test.php?act=2');
    }).then(function(data2) {
      console.log(data2);//處理data2
      return ajax('test.php?act=3');
    }, function(err) {
      console.error(err);
    }).then(function(data3) {
      console.log(data3);
      alert('success');
    }, function(err) {
      console.error(err);
    });
    </script>
    php:
    <?php
    if($_GET['act']==1){
      echo json_encode(array("code"=>200));
    }else if($_GET['act']==2){
      echo json_encode(array("code"=>300));
    }else if($_GET['act']==3){
      echo json_encode(array("code"=>400));
    }
    名單
    以上這篇javascript Promise簡單學(xué)習(xí)使用方法小結(jié)就是小編分享給大家的全部內(nèi)容了,希望能給大家一個參考