最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

一文帶你掌握J(rèn)avaScript異步編程的五種方式

 更新時間:2025年07月01日 08:19:45   作者:程序員小寒  
異步可以理解為把一個任務(wù)分成了兩段,先執(zhí)行第一段,轉(zhuǎn)而去執(zhí)行其它任務(wù),等準(zhǔn)備完畢后,再回過頭來執(zhí)行第二段, 本文主要來和大家聊聊JavaScript異步編程的五種方式,感興趣的可以了解下

1、什么是異步?

異步可以理解為把一個任務(wù)分成了兩段,先執(zhí)行第一段,轉(zhuǎn)而去執(zhí)行其它任務(wù),等準(zhǔn)備完畢后,再回過頭來執(zhí)行第二段。

比如發(fā)一個 http 請求,第一段就是創(chuàng)建 XMLHttpRequest 對象,做好請求配置后向后端發(fā)送請求,然后就去執(zhí)行其他任務(wù)(其它 js 代碼)了,第二段就是拿到后端響應(yīng)后,執(zhí)行對應(yīng)的回調(diào)函數(shù)。

這種不連續(xù)的執(zhí)行,叫做異步,反之,連續(xù)的執(zhí)行,叫做同步。

2、高階函數(shù)

在 js 中,函數(shù)是一等公民。所謂一等公民,就是指函數(shù)能和數(shù)據(jù)類型一樣,可以賦值給變量,也可以作為函數(shù)的參數(shù)和返回值。而傳入的參數(shù)中或者返回值中帶有函數(shù)的,就被稱為高階函數(shù)。

3、高階函數(shù)的作用

3.1 可以批量生成函數(shù)

function isType(type) {
  return (obj) => {
    return Object.prototype.toString.call(obj) === `[object ${type}]`;
  };
}

const isFunc = isType("Function");
const isBoo = isType("Boolean");

通過高階函數(shù)isType,可以生成不同類型的判斷函數(shù),判斷各種對象類型。

3.2 可以用于多次調(diào)用才執(zhí)行的函數(shù)

function after(time, callback) {
  let count = 0;
  return function() {
    if (++count === time) {
      callback.apply(this, arguments);
    }
  };
}
const f = after(3, function() {
  console.log("callback");
});
f();

after函數(shù)的作用是,在調(diào)用f函數(shù)三次之后,才會執(zhí)行回調(diào)函數(shù)callback

4、異步編程的五種實現(xiàn)方式

  • 回調(diào)函數(shù)
  • 事件監(jiān)聽,發(fā)布訂閱
  • Promise
  • generator/yield
  • async/await

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

回調(diào)函數(shù)是指將異步的第二段放在回調(diào)函數(shù)里面,等準(zhǔn)備完畢后,執(zhí)行回調(diào)。

const fs = require("fs");
fs.readFile("./1.txt", "utf8", function(err, data) {
  console.log(err, data);
});

回調(diào)函數(shù)的問題:

1.異常處理麻煩

異步代碼不能用 try catch 捕獲異常,所以如果出錯了要向回調(diào)函數(shù)傳入異常供調(diào)用者判斷。比如在 nodejs 中,對異常處理有一個約定,會將異常作為回調(diào)的第一個參數(shù)返回,如果為 null 則表示沒有出錯。

2.容易形成回調(diào)地獄

異步多級依賴的情況下代碼會嵌套的很深,不利于閱讀和維護(hù)。

const fs = require("fs");
fs.readFile("./1.txt", "utf8", function(err1, result1) {
  fs.readFile(result1, "utf8", function(err2, result2) {
    fs.readFile(result2, "utf8", function(err3, result3) {
      console.log(result3);
    });
  });
});

4.2 事件發(fā)布/訂閱模型

發(fā)布/訂閱是一種設(shè)計模式,它依賴于一個事件調(diào)度中心,先注冊事件名和回調(diào)(on),然后可以主動觸發(fā)(emit)。

const EventEmitter = require("events");
// eve為事件調(diào)度中心
const eve = new EventEmitter();
eve.on("first", function() {
  console.log("first");
});
eve.emit("first");

4.3 Promise

Promise 本意是承諾,在程序中的意思就是承諾我過一段時間后給你一個結(jié)果,而過一段時間指的就是異步操作,比如網(wǎng)絡(luò)請求、定時器,讀取文件等。

const p = new Promise((resolve, reject) => {
  setTimeout(() => {
    resolve("success");
  }, 1000);
});
p.then((result) => {
  // 1秒后打印success
  console.log(result);
});

4.4 Generator/yield

Generator函數(shù)是ES6提供的一種異步編程解決方案。

語法上:可以將它理解為一個狀態(tài)機(jī),其內(nèi)部封裝了多種狀態(tài)。執(zhí)行Generator函數(shù)會返回一個遍歷器對象,可以依次迭代Generator函數(shù)內(nèi)部的每一個狀態(tài),也被稱為迭代器

1.Generator的使用

function *test() {
    const first = yield 1
    console.log(first)
    const second = yield 2
    console.log(second)
}
const it = test()
console.log(it.next())
console.log(it.next('first'))
console.log(it.next('second'))
// { value: 1, done: false }
// first
// { value: 2, done: false }
// second
// { value: undefined, done: true }

注意:第一次調(diào)用next傳遞參數(shù)沒有意義,done的值為false表示函數(shù)調(diào)用結(jié)束了

形式上,Generator函數(shù)相對于普通函數(shù)而言,多了兩個特性。一是function 關(guān)鍵字和函數(shù)名之間有一個星號,函數(shù)內(nèi)部使用yield表達(dá)式,定義不同的內(nèi)部狀態(tài)。yield的意思是產(chǎn)出,可以將狀態(tài)傳遞出去。

2.CO

co 是一個為nodejs和瀏覽器打造的基于生成器的流程控制工具,借助Promise,可以使用更加優(yōu)雅的方式編寫非阻塞代碼。

const fs = require('fs')
function readFile(filename) {
    return new Promise((resolve, reject) => {
        fs.readFile(filename, 'utf8', (err, data) => {
            err ? reject(err) : resolve(data)
        })
    })
}
/** 文件1.txt里面的內(nèi)容是2.txt 
 *  文件2.txt里面的內(nèi)容是222
*/
function *read() {
    const filename = yield readFile('1.txt')
    const result = yield readFile(filename)
    return result
}
co(read).then(result => {
    console.log(result)
}).catch(err => {
    console.log(err)
})
// 最終打印222

co 實現(xiàn)原理如下:

// co實現(xiàn)原理
function co(gen) {
    const it = gen()
    return new Promise((resolve, reject) => {
        !(function next(nextValue) {
            const { value, done } = it.next(nextValue)
            if (!done) {
                value.then(next, reject)
                
            } else {
                resolve(value)
            }
        })()
    })
}

4.5 async/await

async/awaitES7 的語法,是js異步編程的終極解決方案。可以理解為是Promise+Generator的語法糖,可以輕松做到Generator和co所做到的工作。

const fs = require('fs')
function readFile(filename) {
    return new Promise((resolve, reject) => {
        fs.readFile(filename, 'utf8', (err, data) => {
            err ? reject(err) : resolve(data)
        })
    })
}
async function read() {
    const filename = await readFile('1.txt')
    const result = await readFile(filename)
    return result
}
read().then(result => {
    console.log(result)
})

優(yōu)點:

  • 內(nèi)置執(zhí)行器,內(nèi)部會幫你進(jìn)行迭代。
  • 更好的語義,代碼結(jié)構(gòu)清晰
  • 更廣的適用性,await后面不一定要跟promise

缺點:

  • 濫用await會導(dǎo)致性能問題,因為await會阻塞代碼,也許后者不一定依賴前者,但仍需要等待前者完成,導(dǎo)致代碼失去了并發(fā)性。
  • 錯誤處理麻煩,項目中可以用axios攔截器處理錯誤或者用try catch來捕獲錯誤。
  • 經(jīng)過babel編譯后的代碼臃腫。

到此這篇關(guān)于一文帶你掌握J(rèn)avaScript異步編程的五種方式的文章就介紹到這了,更多相關(guān)JavaScript異步編程內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • require.js的用法詳解

    require.js的用法詳解

    本文給大家介紹require.js的用法,require.js的誕生是為了解決兩大問題,第一實現(xiàn)js文件的異步加載,避免網(wǎng)頁失去響應(yīng),第二管理模塊之間的依賴性,便于代碼的編寫和維護(hù),對require.js用法感興趣的朋友可以參考下本篇文章
    2015-10-10
  • JS實現(xiàn)的打字機(jī)效果完整實例

    JS實現(xiàn)的打字機(jī)效果完整實例

    這篇文章主要介紹了JS實現(xiàn)的打字機(jī)效果,結(jié)合完整實例形式分析了javascript定時觸發(fā)自定義函數(shù)模擬打字輸出效果的相關(guān)實現(xiàn)技巧,需要的朋友可以參考下
    2016-06-06
  • uniapp小程序配置tabbar底部導(dǎo)航欄實戰(zhàn)指南

    uniapp小程序配置tabbar底部導(dǎo)航欄實戰(zhàn)指南

    tabBar如果應(yīng)用是一個多tab應(yīng)用,可以通過tabBar配置項指定tab欄的表現(xiàn),以及tab切換時顯示的對應(yīng)頁,下面這篇文章主要給大家介紹了關(guān)于uniapp小程序配置tabbar底部導(dǎo)航欄的相關(guān)資料,需要的朋友可以參考下
    2022-09-09
  • 全面解析Bootstrap中tooltip、popover的使用方法

    全面解析Bootstrap中tooltip、popover的使用方法

    這篇文章主要為大家詳細(xì)解析了Bootstrap中tooltip、popover的使用方法,了解提示框、彈出框的實現(xiàn)原理,感興趣的朋友可以參考一下
    2016-06-06
  • 原生JS實現(xiàn)拖拽位置預(yù)覽

    原生JS實現(xiàn)拖拽位置預(yù)覽

    這篇文章主要為大家詳細(xì)介紹了原生JS實現(xiàn)拖拽位置預(yù)覽,文中示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2021-10-10
  • es6數(shù)組的flat(),flatMap()函數(shù)用法實例分析

    es6數(shù)組的flat(),flatMap()函數(shù)用法實例分析

    這篇文章主要介紹了es6數(shù)組的flat(),flatMap()函數(shù)用法,結(jié)合實例形式分析了es6數(shù)組的flat(),flatMap()函數(shù)基本功能、使用方法及操作注意事項,需要的朋友可以參考下
    2020-04-04
  • 2026前端面試題及答案總結(jié)大全(最新版)

    2026前端面試題及答案總結(jié)大全(最新版)

    這篇文章主要介紹了2026前端面試題及答案總結(jié)的相關(guān)資料,通過示例代碼講解了HTML/CSS盒模型、CSS選擇器優(yōu)先級計算、塊級格式化上下文、JavaScript事件循環(huán)機(jī)制、ES6中變量聲明差異、Promise原理及實現(xiàn)、React與Vue響應(yīng)式機(jī)制與性能優(yōu)化手段等內(nèi)容,需要的朋友可以參考下
    2026-06-06
  • JS實現(xiàn)登錄頁面記住密碼和enter鍵登錄方法推薦

    JS實現(xiàn)登錄頁面記住密碼和enter鍵登錄方法推薦

    下面小編就為大家?guī)硪黄狫S實現(xiàn)登錄頁面記住密碼和enter鍵登錄方法推薦。小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。
    2016-05-05
  • Angular組件拿不到@Input輸入屬性問題探究解決方法

    Angular組件拿不到@Input輸入屬性問題探究解決方法

    最近在工作中實現(xiàn)一個feature的時候,碰到一個小問題:Angular組件拿不到@Input輸入屬性的問題,盡管對這些問題都比較了解,但是找問題是需要一個過程的,所以還是把這個問題總結(jié)記錄了下
    2023-01-01
  • JS計算距當(dāng)前時間的時間差實例

    JS計算距當(dāng)前時間的時間差實例

    下面小編就為大家分享一篇JS計算距當(dāng)前時間的時間差實例,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2017-12-12

最新評論

威海市| 余庆县| 麻江县| 伊春市| 上虞市| 金塔县| 徐闻县| 嘉祥县| 开阳县| 肇州县| 温宿县| 英山县| 高碑店市| 高唐县| 科技| 双柏县| 南川市| 常山县| 乐至县| 满城县| 开封县| 乐清市| 福泉市| 敖汉旗| 清涧县| 长治县| 东丽区| 平阳县| 昂仁县| 资中县| 河池市| 沂水县| 萨嘎县| 随州市| 清原| 城固县| 嘉兴市| 汨罗市| 余姚市| 正阳县| 峨边|