es6之異步編程(學習小結)

最近開始學習es6的新語法特性,我參看的教程是阮一峯老師的教程,這個教程真的寫得非常好,有興趣進行全面學習的夥伴可以參看此教程。教程鏈接:ES6入門教程
相比es5的語法特性,es6最爲突出的兩大特性非module,class和異步編程莫屬。
module,class這部分的改動更貼近於類似Java,C#等後端語言的語法特性。
廢話不多說,首先在進入正題異步編程之前得先明確一件事情:異步編程與多線程編程之間的區別與聯繫? 相信這個問題也是很多夥伴心中的困惑(這個困惑我也有),這裏有一篇大佬寫的對於此問題的詳細解釋的博客,有一語道破天機的奇效:異步編程與多線程編程之間的區別與聯繫
下面,我簡單的闡述一下就js而言,我對此問題的看法。
首先,多線程以及異步編程都是爲了處理線程阻塞的問題,只不過這是兩種完全不同的方式。例如Java,它可以同時開啓多個線程分工進行運作,極大的提高效率。而js是單線程的執行環境,無法開啓多線程,但是爲了解決線程阻塞的情形,所以就產出了異步編程的處理方式。
最傳統的異步編程方式是利用回調函數和事件的方式實現,最常見的場景有settimeout函數,然後es6裏面出現了Promise對象來處理異步請求。
Promise對象裏面有三個最常用的函數,分別是resolve,reject和then。其最簡單的執行流程就是給一個異步操作定義一個promise對象,然後在resolve函數裏定義成功異步時所要調用的函數,在reject函數裏面定義異步請求失敗所需要執行的函數,最後通過then方法來調用異步操作。
promise裏面還有很多具體的細節,大家可以參考教程。
其實Promise在處理異步的方式上相比於傳統的回調函數的方式最大的便利在於,將傳統的多層回調函數嵌套而造成的橫向"回調函數地獄"變成縱向的鏈式結構,即使用then函數。但是此操作也只是對回調函數進行了優化,代碼還是顯得有些冗餘,所以此時新函數Generator 和新關鍵字yield出現了。
這兩組合天生就適合處理這種多狀態的事情。Generator 函數可以暫停函數的執行,返回任意表達式的值。簡單來說,將異步操作寫在yield表達式裏面,等到調用next方法時再往後執行。
最後,主角async,await登場了,其實Generator 以及挺好用了,爲何還要這兩?這兩說白了就是Generator 的語法糖,使得異步操作變得更加方便,可以類比箭頭函數的感覺。
async,await的具體語法我在此也不多敘述,大家可以參看教程。
說了這麼一大串,肯定有人想知道,一個異步編程是不是可以用這三種方式實現?答案是肯定的,在教程async函數這節裏,就有一個案例是使用這三種方法來實現一個異步功能。
最後,我這裏做了一個用異步編程的方式來包裝瀏覽器原生的ajax的demo:
html:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="Access-Control-Allow-Origin" content="https://www.baidu.com/" />
    <title>Document</title>
    <script type="module" src="./main.js"></script>
</head>
<body>
    <button id="ajaxButton" type="button">Make a request</button>
</body>
</html>

main.js:

import Ajax from './ajax.js';

class Main {
  static start() {
    document.getElementById('ajaxButton').addEventListener('click', Main.clickHandler);
  }

  static async clickHandler() {
    const url = './package.json';
    const HTTPMethodType = 'GET';
    const headerMap = new Map();
    headerMap.set('Accept', 'application/json');
    try {
      const result = await Ajax.getPromiseJSON(url, HTTPMethodType, headerMap);
      alert(result);
    } catch (error) {
      alert(error);
    }
  }
}

window.onload = function () {
  Main.start();
};

ajax.js

export default class Ajax {
  static getPromiseJSON(url, HTTPMethodType, headerMap) {
    const promise = new Promise(((resolve, reject) => {
      const handler = function () {
        if (this.status >= 200 && this.status <= 299) {
          resolve(this.response);
        } else if (this.status >= 300 && this.status <= 399) {
          reject(new Error(`${this.status} = Redirects!`));
        } else if (this.status >= 400 && this.status <= 499) {
          reject(new Error(`${this.status} = Client Error!`));
        } else if (this.status >= 500 && this.status <= 599) {
          reject(new Error(`${this.status} = Server Error!`));
        }
      };
      const client = new XMLHttpRequest();
      client.open(HTTPMethodType, url);
      headerMap.forEach((value, key) => {
        client.setRequestHeader(key, value);
      });
      client.onload = handler;
      client.send();
    }));
    return promise;
  }

  static async getAsyncJSON(url, HTTPMethodType, headerMap) {
    const response = await Ajax.getPromiseJSON(url, HTTPMethodType, headerMap);
    return response;
  }
}

最後,es6我也是才學習不久的入門小白,如果有闡述不對的地方或者是由更好的見解歡迎評論區留言,一起交流,共同進步!

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章