js 異步發展簡史

發展歷程:
callback -> pub-sub -> promise -> generator -> async + awaitjavascript

callback

ajax(url, () => {
  // 處理邏輯
  ajax(url1, () => {
    // 處理邏輯
    ajax(url2, () => {
      // 處理邏輯
    });
  });
});

回調地獄,代碼難以維護vue

pub-sub 發佈訂閱

export default class PubSub {
  constructor() {
    // events裏存放的是全部的具名事件
    this.events = {};
  }

  //  提供訂閱功能
  subscribe(event, callback) {
    let self = this;

    if (!self.events.hasOwnProperty(event)) {
      self.events[event] = [];
    }
    // 沒有作去重
    return self.events[event].push(callback);
  }
  // 提供發佈功能
  publish(event, data) {
    let self = this;

    if (!self.events.hasOwnProperty(event)) {
      return [];
    }

    return self.events[event].map(callback => callback(data));
  }
}

參考另外一個工程:
pub-subjava

promise

  • asap源碼能夠看出
    瀏覽器 Promise 事件調度走的是 MutationObserver,node 走的是 process.nextTick
  • Promise 存在三種狀態:
    由 Pending 能夠變爲 Fulfilled 或者 Rejected,切一旦變化就不會再更改
Pending----Promise對象實例建立時候的初始狀態
    Fulfilled----能夠理解爲成功的狀態
    Rejected----能夠理解爲失敗的狀態
Promise.resolve(1) //每次調用返回的都是一個新的Promise實例(這就是then可用鏈式調用的緣由)
  .then(x => x + 1)
  .then(x => {
    throw new Error("My Error"); //若是then中出現異常,會走下一個then的失敗回調
  })
  .catch(() => 1) //return -> 包裝成 Promise.resolve(1)
  .then(x => x + 1)
  .then() //參數穿透
  .then(x => console.log(x)) //2
  .catch(console.error); //catch 會捕獲到沒有捕獲的異常

手寫 Promisenode

缺點:react

  • 沒法取消 Promise
  • 當處於pending狀態時,沒法得知目前進展到哪個階段
  • 錯誤不能被 try catch

生成器 Generators/ yield

迭代器git

Generator 能夠中斷函數的執行,這就爲咱們用同步方式寫異步提供了可能github

function* foo(x) {
  let y = 2 * (yield x + 1); //yield可暫停,next方法可啓動,每次返回的是yield後的表達式結果
  let z = yield y / 3; //yield表達式自己沒有返回值,或者說老是返回undefined。next方法能夠帶一個參數,該參數就會被看成上一個yield表達式的返回值
  return x + y + z;
}
let it = foo(5);
console.log(it.next()); // => {value: 6, done: false}
console.log(it.next(12)); // => {value: 8, done: false}
console.log(it.next(13)); // => {value: 42, done: true}
var fetch = require("node-fetch");
function* gen() {
  var r1 = yield fetch("https://api.github.com/users/github");
  var r2 = yield fetch("https://api.github.com/users/github/followers");
  var r3 = yield fetch("https://api.github.com/users/github/repos");

  console.log([json1.bio, json2[0].login, json3[0].full_name].join("\n"));
}

對於上面三個請求咱們能夠這樣寫ajax

var g = gen();
var result1 = g.next();

result1.value
  .then(function(data) {
    return data.json();
  })
  .then(function(data) {
    return g.next(data).value;
  })
  .then(function(data) {
    return data.json();
  })
  .then(function(data) {
    return g.next(data).value;
  })
  .then(function(data) {
    return data.json();
  })
  .then(function(data) {
    g.next(data);
  });

更好的辦法是使用遞歸json

遞歸
function run(gen) {
  var g = gen();
  function next(data) {
    var result = g.next(data);
    result.value
      .then(function(data) {
        return data.json();
      })
      .then(function(data) {
        next(data);
      });
  }

  next();
}

run(gen);

co這個庫所作的事情
co(gen)即自執行 generatorapi

參考文獻 Generators

async await

自帶 generator 執行器

async //返回一個Promise
  await //後面跟一個Promise
function fetch() {
  return fetchData()
    .then(value1 => {
      return fetchMoreData(value1);
    })
    .then(value2 => {
      return fetchMoreData2(value2);
    });
}

async function fetch() {
  const value1 = await fetchData();
  const value2 = await fetchMoreData(value1);
  return fetchMoreData2(value2);
}
const fetchData = data =>
  new Promise(resolve => setTimeout(resolve, 1000, data + 1));
const fetchValue = async function() {
  var value1 = await fetchData(1);
  var value2 = await fetchData(value1);
  var value3 = await fetchData(value2);
  console.log(value3);
};
fetchValue();

手寫async函數

實際應用:
「異步的」 setState 如何同步獲取 state
這篇文章有詳細的說明

setStateAsync(state){
   return new Promise (resolve =>{
      this.setState(state,resolve)
    })
  }

babel編譯的結果

測試題 2

async function test1() {
  await new Promise(resolve => {
    setTimeout(() => resolve(), 0);
  }).then(() => console.log(1));
  setTimeout(() => console.log(2), 0);
  new Promise(resolve => {
    console.log(3);
    resolve();
  }).then(() => {
    console.log(4);
  });
  console.log(5);
}
test1().then(() => {
  console.log(7);
});
console.log(6);
// 6135472
  • 原文地址 js 異步發展簡史
  • 另外個人博客地址 blog會常常分享 最近的學習內容,項目中遇到的問題及解決方案
相關文章
相關標籤/搜索