JavaScript基礎複習(十一) 異步編程

總是糾結js是異步還是同步?

對於JS 異步還是同步這個問題,不需要糾結太多,在執行DOM渲染時,確實是同步執行的,也是爲了安全起見,一步一步執行,如果上一步未完成,下一步是不會運行的。

但本質還是單線程

但是對於 網絡請求 這樣的場景,一個網絡資源啥時候返回,這個時間是不可預估的,所以不能傻傻的等着,也就是這樣,設計了異步,不管返回結果,執行後就執行下一步,上一步的執行結果什麼時候返回,就什麼時候再返回。

實現異步的最核心原理,就是將callback作爲參數傳遞給異步執行函數,當有結果返回之後再觸發callback執行

常見的異步操作

  • 網絡請求, 如ajax , http.get
  • IO 操作, 如readFile, readdir
  • 定時函數, 如setTimeout, setInterval

網絡請求實現發展:

1、回調 2、promise 3、Generator 4、async/await

回調

對於這種傳遞過去不執行,等出來結果之後再執行的函數,叫做callback,即回調函數,如ajax操作中

使用場景

  • 事件回調
  • Node API
  • setTimeOut/setInterval中的回調函數
  • ajax請求

優點: 簡單;

缺點: 不能 try catch; 產生回調地獄

使用

// 比較常見的有ajax
$.ajax('http://www.wyunfei.com/', {
 success (res) {
   // 這裏可以監聽res返回的數據做回調邏輯的處理
 }
})

// 或者在頁面加載完畢後回調
$(function() {
 // 頁面結構加載完成,做回調邏輯處理
})

promise

承諾未來會執行,有三種狀態,分別是: pedding 未完成, resolved 成功, rejected 失敗。

狀態改變,只有兩種情況

  • pedding -> resolved
  • pedding -> rejected。當promise狀態發生改變,就會觸發then()裏的響應函數處理後續步驟,.then()返回一個新的promise實例,所以可以鏈式調用

特點

  • 狀態一經改變,不會再變化
  • 異步操作可以簡化爲同步操作,避免層層調用

從表面上看,可以解決回調地獄的問題,但是實際上並沒有解決,在使用中,仍然需要有.then()的不斷調用

缺點

  • 不能取消promise
  • 不能try catch
  • pedding狀態時,不知道現在進展到哪一個階段

Promise.all([1,2,3]) 可以實現多個異步並行執行,同一時刻獲取最終結果的問題,當子Promise全部完成,該Promise完成,返回全部值的數組;當有一個子promise失敗,該promise失敗,返回第一個失敗的結果。

Promise.race() 同上,但只要有一個成功,就返回成功的結果

使用

new Promise(function(resolve, reject) {
    // 一段耗時的一步操作
    resolve('success');
    // reject('fail');
}).then(
    (res)=>{console.log(res)},
    (err)=>{console.log(err)}
)

Generator

generator和函數不同的是,generatorfunction* 定義(注意多出的*號),並且,除了return語句,還可以用yield返回多次;可以在執行過程中多次返回

使用 .next() next方法可以帶一個參數,該參數就會被當作上一個yield表達式的返回值。每一次的next()調用,執行一次yield

使用

function* gen() {
    let a = yield 111;
    console.log(a);
    let b = yield 222;
    console.log(b);
    let c = yield 333;
    console.log(c);
    let d = yield 444;
    console.log(d);
}
let t = gen();
//next方法可以帶一個參數,該參數就會被當作上一個yield表達式的返回值
t.next(1); //第一次調用next函數時,傳遞的參數無效
t.next(2); //a輸出2;
t.next(3); //b輸出3; 
t.next(4); //c輸出4;
t.next(5); //d輸出5;

try {
    // r1 = yield ajax('http://url-1', data1);
    // r2 = yield ajax('http://url-2', data2);
    // r3 = yield ajax('http://url-3', data3);
    // success(r3);
}
catch (err) {
    // handle(err);
}


async/await

其實就是實現了將 Generator函數和自動執行器(co),包裝在一個函數中

基本兼容上面異步方式的 缺點

使用

const fs = require('fs');
const bluebird = require('bluebird');
const readFile = bluebird.promisify(fs.readFile);


async function read() {
    await readFile(A, 'utf-8');
    await readFile(B, 'utf-8');
    await readFile(C, 'utf-8');
    //code
}

read().then((data) => {
    //code
}).catch(err => {
    //code
});

關注我獲取更多前端資源和經驗分享
在這裏插入圖片描述

感謝大佬們閱讀,希望大家頭髮濃密,睡眠良好,情緒穩定,早日實現財富自由~

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