JS-Promise(使異步操做同步執行)

單個異步操做同步

<div id="box"></div>
<script>
  var box = document.querySelector('#box')
  var p = new Promise(function(resolve, reject){
    setTimeout(function(){
      box.innerHTML += '網絡請求<br>';
      resolve()
    }, 1000)
  })
  p.then(function(resolve){
    box.innerHTML += '結束<br><hr>';
  })
</script>

肯定個數異步操做同步

<div id="box"></div>
<script>
  var p = new Promise(function(resolve, reject){
    setTimeout(function(){
      box.innerHTML += '創建鏈接<br>';
      resolve('ok')
    }, 1000)
  })
  function post_sth(data){
    return new Promise(function(resolve, reject){
      setTimeout(function(){
        box.innerHTML += 'post網絡請求,此時data='+data+' <br>';
        resolve(data+'|post')
      }, 1000)
    })
  }
  function get_sth(data){
    return new Promise(function(resolve, reject){
      setTimeout(function(){
        box.innerHTML += 'get網絡請求,此時data='+data+' <br>';
        resolve(data+'|get')
      }, 1000)
    })
  }
  
  p.then(post_sth).then(get_sth).then(post_sth).then(function(data){
    box.innerHTML += '最後data='+data+'<br><hr>';
  });
</script>

不定個數異步操做同步

<div id="box"></div>
<script>
  var p = new Promise(function(resolve, reject){resolve()})
  /**
    function
      返回function(供本then用)
        返回Promise(供下一個then用)
  */
  function get_request_sth_func(i){
    return function request_sth(){
      return new Promise(function(resolve, reject){
        setTimeout(function(){
          box.innerHTML += '請求'+i+'<br>';
          resolve()
        }, Math.round(Math.random()*1000))
      })
    }
  }
  for (var i = 0; i < 20; ++i) {
    p = p.then(get_request_sth_func(i))
  }
  p.then(function(){
    box.innerHTML += '完成<br><hr>';
  })
</script>

處理異常

  • 使用obj.catch(onRejected)obj.then(undefined, onRejected)處理。promise

  • Promise 內的異常沒法拋出到Promise外部,只能在上述的回調函數中處理(和setTimeout() process.nextTick()相似,Promise也會生成新的調用棧)。網絡

async function

https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Statements/async_functiondom

原理

function Promise(fn) {
  var state = "pending",
    value = null,
    callbacks = [];

  /**
   * promise 的 then 方法
   * @returns {Promise}
   */
  this.then = function(onFulfilled, onRejected) {
    return new Promise(function(resolve, reject) {
      handle({
        onFulfilled: onFulfilled || null,
        onRejected: onRejected || null,
        resolve: resolve,
        reject: reject
      });
    });
  };

  /**
   * 根據 promise 的 state 處理 callback
   * @param {Object} callback
   */
  function handle(callback) {
    if (state === "pending") {
      callbacks.push(callback);
      return;
    }

    var cb = state === "fulfilled" ? callback.onFulfilled : callback.onRejected,
      ret;
    if (cb === null) {
      cb = state === "fulfilled" ? callback.resolve : callback.reject;
      cb(value);
      return;
    }
    try {
      ret = cb(value);
      callback.resolve(ret);
    } catch (e) {
      callback.reject(e);
    }
  }

  /**
   * 執行 promise 的 resolve
   * @param {*} newValue
   */
  function resolve(newValue) {
    if (
      newValue &&
      (typeof newValue === "object" || typeof newValue === "function")
    ) {
      var then = newValue.then;
      if (typeof then === "function") {
        then.call(newValue, resolve, reject);
        return;
      }
    }
    state = "fulfilled";
    value = newValue;
    execute();
  }

  /**
   * 執行 promise 的 reject
   * @param {*} reason
   */
  function reject(reason) {
    state = "rejected";
    value = reason;
    execute();
  }

  /**
   * 執行 promise 的所有回調函數
   */
  function execute() {
    setTimeout(function() {
      callbacks.forEach(function(callback) {
        handle(callback);
      });
    }, 0);
  }

  // 調用 new Promise 時傳入的函數
  fn(resolve, reject);
}

/**
 * promise -> promise2 -> promise3
 *        \
 *         -> promise4
 */

// new Promise 調用傳入的函數,參數爲 Promise 內部的的 reslove 和 reject 函數
let promise = new Promise(res => setTimeout(() => res("t1"), 1000));

promise
  // 調用 then 方法返回一個新的 Promise(promise2),這個 Promise 的參數爲 handle 函數
  // promise2
  .then(d => {
    console.log(d); // t1
    return "t2";
  })
  // promise3
  .then(d => {
    console.log(d);
    return "t3"; // t2
  });

promise
  // promise4
  .then(d => {
    console.log(d); // t1
  });

參考

相關文章
相關標籤/搜索