91网首页-91网页版-91网在线观看-91网站免费观看-91网站永久视频-91网站在线播放

LOGO OA教程 ERP教程 模切知識(shí)交流 PMS教程 CRM教程 開發(fā)文檔 其他文檔  
 
網(wǎng)站管理員

一杯咖啡☕️的時(shí)間,聊聊 js 異步解決方案

freeflydom
2023年7月29日 9:42 本文熱度 1222

回調(diào)函數(shù)(callback)

回調(diào)函數(shù) 簡(jiǎn)單理解就是一個(gè)函數(shù)被作為參數(shù)傳遞給另一個(gè)函數(shù)?;卣{(diào)是早期最常用的一種異步解決方案。

回調(diào)并不一定就是異步,并沒有直接關(guān)系。

舉個(gè)簡(jiǎn)單的例子:

function f1(cb) {

  setTimeout(() => {

    cb && cb();

  }, 2000);

}


f1(() => {

  console.log("1");

});

如上,我們使用 setTimeout 在函數(shù) f1 中模擬了一個(gè)耗時(shí) 2s 的任務(wù),耗時(shí)任務(wù)結(jié)束后會(huì)拋出一個(gè)回調(diào),那么我們?cè)谡{(diào)用時(shí)就可以做到在函數(shù) f1 的耗時(shí)任務(wù)結(jié)束后執(zhí)行回調(diào)函數(shù)了。

采用這種方式,我們把同步操作變成了異步操作,f1 不會(huì)堵塞程序運(yùn)行,相當(dāng)于先執(zhí)行程序的主要邏輯,將耗時(shí)的操作推遲執(zhí)行。

回調(diào)優(yōu)缺點(diǎn)

優(yōu)點(diǎn):簡(jiǎn)單、容易理解

缺點(diǎn):代碼不優(yōu)雅,可讀性差,不易維護(hù),高度耦合,層層嵌套造成回調(diào)地獄

事件監(jiān)聽(發(fā)布訂閱模式)

發(fā)布訂閱模式 定義了對(duì)象間的一種一對(duì)多的依賴關(guān)系,當(dāng)一個(gè)對(duì)象的狀態(tài)發(fā)生改變時(shí),所有依賴于它的對(duì)象都將會(huì)得到通知。

其實(shí)我們都用過(guò)發(fā)布訂閱模式,比如我們?cè)?DOM 節(jié)點(diǎn)上綁定一個(gè)事件函數(shù):

document.body.addEventListener('click', function () {

  console.log('點(diǎn)擊');

})

但這只是對(duì)發(fā)布訂閱模式最簡(jiǎn)單的使用,在很多場(chǎng)景下我們經(jīng)常會(huì)使用一些自定義事件來(lái)滿足我們的需求。

發(fā)布訂閱模式有很多種實(shí)現(xiàn)方式,下面我們用 class 來(lái)簡(jiǎn)單實(shí)現(xiàn)下:

class Emitter {

  constructor() {

    // _listener數(shù)組,key為自定義事件名,value為執(zhí)行回調(diào)數(shù)組-因?yàn)榭赡苡卸鄠€(gè)

    this._listener = []

  }


  // 訂閱 監(jiān)聽事件

  on(type, fn) {

    // 判斷_listener數(shù)組中是否存在該事件命

    // 存在將回調(diào)push到事件名對(duì)應(yīng)的value數(shù)組中,不存在直接新增

    this._listener[type] 

      ? this._listener[type].push(fn) 

    : (this._listener[type] = [fn])

  }


  // 發(fā)布 觸發(fā)事件

  trigger(type, ...rest) {

    // 判斷該觸發(fā)事件是否存在

    if (!this._listener[type]) return

    // 遍歷執(zhí)行該事件回調(diào)數(shù)組并傳遞參數(shù)

    this._listener[type].forEach(callback => callback(...rest))

  }

}

如上所示,我們創(chuàng)建了一個(gè) Emitter 類,并且添加了兩個(gè)原型方法 ontrigger,使用如下:

// 創(chuàng)建一個(gè)emitter實(shí)例

const emitter = new Emitter()


emitter.on("done", function(arg1, arg2) {

  console.log(arg1, arg2)

})


emitter.on("done", function(arg1, arg2) {

  console.log(arg2, arg1)

})


function fn1() {

  console.log('我是主程序')

  setTimeout(() => {

    emitter.trigger("done", "異步參數(shù)一", "異步參數(shù)二")

  }, 1000)

}


fn1()

我們先創(chuàng)建一個(gè) emitter 實(shí)例,接著注冊(cè)事件,再觸發(fā)事件,也解決了異步問(wèn)題。

事件監(jiān)聽優(yōu)缺點(diǎn)

優(yōu)點(diǎn):比較符合模塊化思想,我們自寫監(jiān)聽器時(shí)可以做很多優(yōu)化從而更好地監(jiān)控程序運(yùn)行。

缺點(diǎn):整個(gè)程序變成了事件驅(qū)動(dòng),流程上或多或少都會(huì)有點(diǎn)影響,每次使用還得注冊(cè)事件監(jiān)聽再進(jìn)行觸發(fā)挺麻煩的,代碼也不太優(yōu)雅。

Promise

ES2015(ES6)標(biāo)準(zhǔn)化和引入了 Promise 對(duì)象,它是異步編程的一種解決方案。

簡(jiǎn)單來(lái)說(shuō)就是用同步的方式寫異步的代碼,可用來(lái)解決回調(diào)地獄問(wèn)題。

Promise 對(duì)象狀態(tài)一旦改變,就不會(huì)再變,只有兩種變化可能:

  1. Pending 變?yōu)?Resolved

  2. Pending 變?yōu)?Rejected

我們用 setTimeout 模擬異步操作:

function analogAsync(n) {

  return new Promise((resolve) => {

    setTimeout(() => resolve(n + 500), n);

  });

}


function fn1(n) {

  console.log(`step1 with ${n}`);

  return analogAsync(n);

}


function fn2(n) {

  console.log(`step2 with ${n}`);

  return analogAsync(n);

}


function fn3(n) {

  console.log(`step3 with ${n}`);

  return analogAsync(n);

}

Promise 來(lái)實(shí)現(xiàn):

function fn() {

  let time1 = 0;

  fn1(time1)

    .then((time2) => fn2(time2))

    .then((time3) => fn3(time3))

    .then((res) => {

      console.log(`result is ${res}`);

    });

}


fn();

Promise 優(yōu)缺點(diǎn)

優(yōu)點(diǎn):Promise 用同步的方式寫異步的代碼,避免了層層嵌套的回調(diào)函數(shù),可讀性更好。鏈?zhǔn)讲僮鳎梢栽?then 中繼續(xù)寫 Promise 對(duì)象并返回,然后繼續(xù)調(diào)用 then 來(lái)進(jìn)行回調(diào)操作。

缺點(diǎn):Promise 對(duì)象一旦新建就會(huì)立即執(zhí)行,無(wú)法中途取消。若不設(shè)置回調(diào)函數(shù),Promise 內(nèi)部會(huì)拋出錯(cuò)誤,不會(huì)流到外部。

Generator

Generator 其實(shí)是一個(gè)函數(shù),只不過(guò)是一個(gè)特殊的函數(shù)。普通函數(shù),你執(zhí)行了這個(gè)函數(shù),函數(shù)內(nèi)部不會(huì)停,直到這個(gè)函數(shù)結(jié)束。Generator 這個(gè)函數(shù)特殊之處就是中間可以停。

示例:

function *generatorFn() {

  console.log("a");

  yield '1';

  console.log("b");

  yield '2'; 

  console.log("c");

  return '3';

}


let it = generatorFn();

it.next();

it.next();

it.next();

it.next();

上面這個(gè)示例就是一個(gè) Generator 函數(shù),它有如下特點(diǎn):

  • 不同于普通函數(shù),Generator 函數(shù)在 function 后面,函數(shù)名之前有個(gè) *

  • 函數(shù)內(nèi)部有 yield 字段

  • 調(diào)用后其函數(shù)返回值使用了 next 方法

Generator 優(yōu)缺點(diǎn)

優(yōu)點(diǎn):優(yōu)雅的流程控制方式,可以讓函數(shù)可中斷執(zhí)行

缺點(diǎn):Generator 函數(shù)的執(zhí)行必須靠執(zhí)行器,只針對(duì)異步處理來(lái)說(shuō),還是不太方便

async/await

ES2017 標(biāo)準(zhǔn)引入了 async 函數(shù),使得異步操作變得更加方便。async 是異步的意思,而 await 是 async wait 的簡(jiǎn)寫,即異步等待,async/await 的出現(xiàn),被很多人認(rèn)為是 js 異步操作的最終且最優(yōu)雅的解決方案。

async 在做什么

async 函數(shù)返回的是一個(gè) Promise 對(duì)象,如果在 async 函數(shù)中直接 return 一個(gè)直接量,async 會(huì)把這個(gè)直接量通過(guò) Promise.resolve() 封裝成 Promise 對(duì)象返回。

await 在等待什么

await 等待的是一個(gè)表達(dá)式,這個(gè)表達(dá)式的計(jì)算結(jié)果是 Promise 對(duì)象或者其它值(換句話說(shuō),就是沒有特殊限定,啥都行)。

  • 如果 await 后面不是 Promise 對(duì)象,直接執(zhí)行

  • 如果 await 后面是 Promise 對(duì)象會(huì)阻塞后面的代碼,Promise 對(duì)象 resolve,然后得到 resolve 的值,作為 await 表達(dá)式的運(yùn)算結(jié)果

  • await 只能在 async 函數(shù)中使用

上述用 setTimeout 模擬異步操作,我們用 async/await 來(lái)實(shí)現(xiàn):

async function fn() {

  let time1 = 0;

  let time2 = await fn1(time1);

  let time3 = await fn2(time2);

  let res = await fn3(time3);

  console.log(`result is ${res}`);

}


fn();

輸出結(jié)果和上面用 Promise 實(shí)現(xiàn)是一樣的,但這個(gè) async/await 代碼結(jié)構(gòu)看起來(lái)清晰得多,幾乎跟同步寫法一樣,十分優(yōu)雅。

async/await 優(yōu)缺點(diǎn)

優(yōu)點(diǎn):內(nèi)置執(zhí)行器,更好的語(yǔ)義,更廣的適用性

缺點(diǎn):濫用 await 可能會(huì)導(dǎo)致性能問(wèn)題,因?yàn)?nbsp;await 會(huì)阻塞代碼


原文鏈接



該文章在 2023/7/29 9:42:29 編輯過(guò)
關(guān)鍵字查詢
相關(guān)文章
正在查詢...
點(diǎn)晴ERP是一款針對(duì)中小制造業(yè)的專業(yè)生產(chǎn)管理軟件系統(tǒng),系統(tǒng)成熟度和易用性得到了國(guó)內(nèi)大量中小企業(yè)的青睞。
點(diǎn)晴PMS碼頭管理系統(tǒng)主要針對(duì)港口碼頭集裝箱與散貨日常運(yùn)作、調(diào)度、堆場(chǎng)、車隊(duì)、財(cái)務(wù)費(fèi)用、相關(guān)報(bào)表等業(yè)務(wù)管理,結(jié)合碼頭的業(yè)務(wù)特點(diǎn),圍繞調(diào)度、堆場(chǎng)作業(yè)而開發(fā)的。集技術(shù)的先進(jìn)性、管理的有效性于一體,是物流碼頭及其他港口類企業(yè)的高效ERP管理信息系統(tǒng)。
點(diǎn)晴WMS倉(cāng)儲(chǔ)管理系統(tǒng)提供了貨物產(chǎn)品管理,銷售管理,采購(gòu)管理,倉(cāng)儲(chǔ)管理,倉(cāng)庫(kù)管理,保質(zhì)期管理,貨位管理,庫(kù)位管理,生產(chǎn)管理,WMS管理系統(tǒng),標(biāo)簽打印,條形碼,二維碼管理,批號(hào)管理軟件。
點(diǎn)晴免費(fèi)OA是一款軟件和通用服務(wù)都免費(fèi),不限功能、不限時(shí)間、不限用戶的免費(fèi)OA協(xié)同辦公管理系統(tǒng)。
Copyright 2010-2025 ClickSun All Rights Reserved

主站蜘蛛池模板: 国产精品日韩免费看 | 91午夜视| 成人国产综 | 精品在线中| 午夜国产免费 | 尤物精品 | 国产疯狂女同互磨高 | 日韩国产精品一区 | 91免费精品 | 国产夏晴子免费福利 | 国产亚洲精品久 | 国产成视频| 欧美日女人b视频网 | 理论片午夜 | 果冻文化传媒官网 | 乱伦综合国产免费 | 国产a级自拍 | 欧美一区日韩专区 | 国产黑丝视频 | 国产国产在线观看 | 中文字幕亚洲无限码 | 日本乱人 | 国产亚洲欧美性爱 | 九九这里只有精品 | 国精产品永久999 | 国产不卡牛在线观看 | 99精品蜜臀蜜 | 91九色国产蝌蚪 | 国产乱子伦在线视频 | 中文字幕日韩电影 | 国内成人精品亚洲 | 国产亚洲女在线精品 | 国产精品亲子乱 | 日韩理论午夜 | 91香蕉在线播放 | 精品免费一区二区三 | 日本成人AB在线 | 福利片午夜免费观着 | 国产精品日产三 | 91国产美女脚交 | 中文字字幕乱码 |