JS異步編程

#### JS 異步編程

#### http://www.reibang.com/p/9bfb68c585bc

#### https://blog.csdn.net/weixin_48820137/article/details/108850610

#### https://juejin.im/post/6877438201657557005/

#### JavaScript異步編程

單線程: JS執(zhí)行環(huán)境中負責執(zhí)行代碼的線程只有一個

優(yōu)點: 更安全更簡單

缺點: 耗時任務阻塞

#### 同步模式---調用棧(Call stack)排隊執(zhí)行

#### 異步模式

不會去等待這個任務的結束才開始下一個任務

開啟過后立即往后執(zhí)行下一個任務

后續(xù)邏輯一般會通過回調函數(shù)的方式定義

消息隊列(Queue)和事件循環(huán)(Event loop)

運行環(huán)境提供的API是以同步或異步模式的方式工作

**EventLoop** 是一種循環(huán)機制 外永,不斷去輪詢一些隊列 策橘,從中找到 需要執(zhí)行的任務并按順序執(zhí)行的一個執(zhí)行模型回论。

**消息隊列** 是用來存放宏任務的隊列犹撒, 比如定時器時間到了, 定時間內傳入的方法引用會存到該隊列逻卖, ajax回調之后的執(zhí)行方法也會存到該隊列杈绸。

一開始整個腳本作為一個宏任務執(zhí)行。執(zhí)行過程中同步代碼直接執(zhí)行檬贰,宏任務等待時間到達或者成功后,將方法的回調放入宏任務隊列中缺亮,微任務進入微任務隊列翁涤。

當前主線程的宏任務執(zhí)行完出隊,檢查并清空微任務隊列萌踱。接著執(zhí)行瀏覽器 UI 線程的渲染工作葵礼,檢查web worker 任務,有則執(zhí)行。

然后再取出一個宏任務執(zhí)行。以此循環(huán)...

**宏任務**可以理解為每次執(zhí)行棧執(zhí)行的代碼就是一個宏任務(包括每次從事件隊列中獲取一個事件回調并放到執(zhí)行棧中執(zhí)行)。

瀏覽器為了讓 JS 內部宏任務 與 DOM 操作能夠有序的執(zhí)行,會在一個宏任務執(zhí)行結束后芦缰,在下一個宏任務執(zhí)行開始前,對頁面進行重新渲染高职。

? 宏任務包含:script(整體代碼)藐吮、setTimeout、setInterval卤档、I/O蝙泼、UI交互事件、MessageChannel 等

**微任務**可以理解是在當前任務執(zhí)行結束后需要立即執(zhí)行的任務劝枣。也就是說汤踏,在當前任務后,在渲染之前舔腾,執(zhí)行清空微任務溪胶。

所以它的響應速度相比宏任務會更快,因為無需等待 UI 渲染稳诚。

微任務包含:Promise.then哗脖、MutaionObserver、process.nextTick(Node.js 環(huán)境)等

#### Promise

三個狀態(tài) Pending Fulfilled-onFulfilled Rejected-onRejected

狀態(tài)更改之后不可修改

#### promise 基本用法

const promise = new Promise(function(resolve, reject){

? ? // foo()

? ? // throw new Errow('error')

? ? resolve(100)

? ? // reject(new Error("promise rejected"))

})

// promise.then(function(value){

//? ? console.log('resolved', value)

// }, function(error){

//? ? console.log('rejected', error)

// })

// console.log('end')

#### Promise 常見誤區(qū)---回調嵌套

#### Promise 鏈式調用

then方法會返回一個全新的Promise對象

后面的then方法就是在為上一個then返回的Promise注冊回調

前面then方法中的回調函數(shù)的返回值會作為后面then方法回調的參數(shù)

如果回調中返回的是Promise, 那么后面then方法的回調會等待它的結束

let promise2 = promise.then(function(value){

? ? console.log('resolved', value)

}, function(error){

? ? console.log('rejected', error)

}) .then(function(value){

? ? console.log('resolved', value)

}, function(error){

? ? console.log('rejected', error)

}) .then(function(value){

? ? console.log('resolved', value)

}, function(error){

? ? console.log('rejected', error)

})

console.log(promise2 === promise)

promise.then(function(value){

? ? console.log('resolved', value)

}).catch(error => {

? ? console.log("error", error)

})

#### Promise 異常處理

Promise實例的catch方法 then方法中的失敗回調

區(qū)別: (1)then注冊失敗回調只能捕獲到前一個promise的異常

(2)catch是給整個Promise鏈條注冊的失敗回調

#### Promise 靜態(tài)方法

resolve() reject()

Promise 靜態(tài)方法 Promise.resolve() Promise.reject()

三種是等價的? 有thenable接口的函數(shù)

Promise.resolve('f00').then( value => {

? ? console.log('resolve', value)

})

Promise.resolve({

? ? then: (onFulfilled, onRejected) => {

? ? ? ? onFulfilled('f00')

? ? }

}).then(value => {

? ? console.log(value)

})

new Promise((resolve, reject) => {

? ? resolve('f00')

}).then(value => {

? ? console.log('new', value)

})

Promise.reject(new Error('rejected')).catch(error => {

? ? console.log('error', error)

})

#### Promise 并行執(zhí)行

all()方法 race()方法

#### Promise 執(zhí)行時序 / 宏任務 微任務

微任務: 提高整體的響應能力

Promise 執(zhí)行時序 / 宏任務 微任務

console.log('global start')

setTimeout(()=>{

? ? console.log('setTimeout1')

}, 1000)

setTimeout(()=>{

? ? console.log('setTimeout')

}, 100)

Promise.resolve().then(()=>{

? ? console.log('promise')

}).then(()=>{

? ? console.log('promise1')

})

console.log('global end')

#### Generator異步方案

//Generator異步方案

function *foo(){

? ? console.log("start")

? ? try{

? ? ? ? const res = yield 'foo'

? ? ? ? console.log(res, 'res')

? ? }catch(e){

? ? ? ? console.log(e, 'e')

? ? }


}

const generator = foo()

const result = generator.next()

console.log(result, 'result')

generator.next('bar')

generator.throw(new Error('Generator Error'))

//管理異步流程 體驗Generator 函數(shù)異步方案

function *main(){

? ? try{

? ? ? ? const users = yield promise

? ? ? ? console.log('users', users)


? ? ? ? const posts = yield Promise.resolve(200)

? ? ? ? console.log(posts, 'posts')

? ? }catch(e){

? ? ? ? console.log(e)

? ? }


}

const g = main()

const result = g.next()

result.value.then(data => {

? ? const result2 = g.next(data)

? ? if(result2.done) return

? ? result2.value.then(data => {

? ? ? ? g.next(data)

? ? })

})

//遞歸執(zhí)行Generator函數(shù)

const g = main()

function handleResult (result){

? ? if(result.done) return

? ? result.value.then(data => {

? ? ? ? handleResult(g.next(data))

? ? }, error => {

? ? ? ? g.throw(error)

? ? })

}

handleResult(g.next())

function co(generator){

? ? const g = generator()

? ? function handleResult (result){

? ? ? ? if(result.done) return

? ? ? ? result.value.then(data => {

? ? ? ? ? ? handleResult(g.next(data))

? ? ? ? }, error => {

? ? ? ? ? ? g.throw(error)

? ? ? ? })

? ? }

? ? handleResult(g.next())

}

co(main)

#### Async/ Await 語法糖 語言層面的異步編程標準

async function mainSync(){

? ? try{

? ? ? ? const users = await promise

? ? ? ? console.log('users', users)


? ? ? ? const posts = await Promise.resolve(200)

? ? ? ? console.log(posts, 'posts')

? ? }catch(e){

? ? ? ? console.log(e)

? ? }

}

const mains = mainSync()

mains.then(()=>{

? ? console.log('all completed')

})

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
  • 序言:七十年代末扳还,一起剝皮案震驚了整個濱河市才避,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌氨距,老刑警劉巖桑逝,帶你破解...
    沈念sama閱讀 219,427評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異俏让,居然都是意外死亡楞遏,警方通過查閱死者的電腦和手機茬暇,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,551評論 3 395
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來寡喝,“玉大人而钞,你說我怎么就攤上這事【械矗” “怎么了臼节?”我有些...
    開封第一講書人閱讀 165,747評論 0 356
  • 文/不壞的土叔 我叫張陵,是天一觀的道長珊皿。 經(jīng)常有香客問我网缝,道長,這世上最難降的妖魔是什么蟋定? 我笑而不...
    開封第一講書人閱讀 58,939評論 1 295
  • 正文 為了忘掉前任粉臊,我火速辦了婚禮,結果婚禮上驶兜,老公的妹妹穿的比我還像新娘扼仲。我一直安慰自己,他們只是感情好抄淑,可當我...
    茶點故事閱讀 67,955評論 6 392
  • 文/花漫 我一把揭開白布屠凶。 她就那樣靜靜地躺著,像睡著了一般肆资。 火紅的嫁衣襯著肌膚如雪矗愧。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,737評論 1 305
  • 那天郑原,我揣著相機與錄音唉韭,去河邊找鬼。 笑死犯犁,一個胖子當著我的面吹牛属愤,可吹牛的內容都是我干的。 我是一名探鬼主播酸役,決...
    沈念sama閱讀 40,448評論 3 420
  • 文/蒼蘭香墨 我猛地睜開眼住诸,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了簇捍?” 一聲冷哼從身側響起只壳,我...
    開封第一講書人閱讀 39,352評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎暑塑,沒想到半個月后吼句,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,834評論 1 317
  • 正文 獨居荒郊野嶺守林人離奇死亡事格,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 37,992評論 3 338
  • 正文 我和宋清朗相戀三年惕艳,在試婚紗的時候發(fā)現(xiàn)自己被綠了搞隐。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 40,133評論 1 351
  • 序言:一個原本活蹦亂跳的男人離奇死亡远搪,死狀恐怖劣纲,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情谁鳍,我是刑警寧澤癞季,帶...
    沈念sama閱讀 35,815評論 5 346
  • 正文 年R本政府宣布,位于F島的核電站倘潜,受9級特大地震影響绷柒,放射性物質發(fā)生泄漏。R本人自食惡果不足惜涮因,卻給世界環(huán)境...
    茶點故事閱讀 41,477評論 3 331
  • 文/蒙蒙 一废睦、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧养泡,春花似錦嗜湃、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,022評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至输硝,卻和暖如春今瀑,著一層夾襖步出監(jiān)牢的瞬間程梦,已是汗流浹背点把。 一陣腳步聲響...
    開封第一講書人閱讀 33,147評論 1 272
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留屿附,地道東北人郎逃。 一個月前我還...
    沈念sama閱讀 48,398評論 3 373
  • 正文 我出身青樓,卻偏偏與公主長得像挺份,于是被迫代替她去往敵國和親褒翰。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 45,077評論 2 355