国产 无码 综合区,色欲AV无码国产永久播放,无码天堂亚洲国产AV,国产日韩欧美女同一区二区

【前端】淺談async/await異步傳染性

這篇具有很好參考價值的文章主要介紹了【前端】淺談async/await異步傳染性。希望對大家有所幫助。如果存在錯誤或未考慮完全的地方,請大家不吝賜教,您也可以點擊"舉報違法"按鈕提交疑問。

概述

"異步傳染性"問題通常是指,當(dāng)一個函數(shù)使用了async和await,其調(diào)用者也需要使用async和await處理異步操作,導(dǎo)致整個調(diào)用鏈都變成異步的。這種情況可能導(dǎo)致代碼變得更復(fù)雜,不易維護。

類似于C# try catch的層層上拋,在某一層catch

觀點

查了很多資料 ,對于這個問題說法還都不一樣

  1. async/await異步傳染性無法解決
  2. 可以解決但開銷不小/ 解決代價不大

無法解決

在node 的層面沒法解決, 除非v8 或者jscore等等提供 GMP 模型+Socket 勾子。

不是該考慮怎么消除async,而是該考慮怎么在需要的時候給任意程序入口加一個異步上下文。除此之外任何想要在程序中段消除async的需求都是偽需求。

可以解決

  • 合理分層:將異步操作集中在特定層次,例如數(shù)據(jù)訪問層或API調(diào)用層,這樣可以將異步操作限制在這些層次,而不會傳播到整個代碼庫。在這種架構(gòu)下,其他層次的代碼可以保持同步方式處理數(shù)據(jù),從而降低代碼復(fù)雜度。
  • 使用Promise:當(dāng)使用async和await時,實際上底層是基于Promise的。你可以盡量使用Promise鏈式調(diào)用(.then()和.catch()),在某種程度上減少異步傳染性。但請注意,過度使用Promise鏈式調(diào)用可能導(dǎo)致回調(diào)地獄問題。
  • 使用事件驅(qū)動:異步傳染性問題有時候是因為代碼邏輯緊密耦合所導(dǎo)致的??紤]使用事件驅(qū)動架構(gòu),通過發(fā)布和訂閱事件的方式來解耦代碼。這樣,即使某個操作是異步的,它也不會影響到其他操作的同步性。
  • 限制異步操作的范圍:盡量讓異步操作獨立,不要過多地依賴其他異步操作的結(jié)果。如果確實需要依賴其他異步操作的結(jié)果,嘗試將這些操作分組,并使用Promise.all()或Promise.race()等方法來處理。
  • 避免不必要的異步操作:不要將原本可以用同步方式實現(xiàn)的操作變成異步操作。異步操作應(yīng)該只用于真正需要的場景,例如網(wǎng)絡(luò)請求、文件讀寫等。
  • ES2021 可以用top-level await
  • 封裝異步操作:將需要異步操作的函數(shù)封裝成一個單獨的函數(shù),該函數(shù)內(nèi)部使用 async/await
    來處理異步邏輯。然后,在需要調(diào)用這個異步函數(shù)的地方,可以直接調(diào)用它,而不需要在調(diào)用者處添加 async/await。
  • 使用異步函數(shù)的返回值:如果調(diào)用異步函數(shù)的結(jié)果在調(diào)用者中不需要立即使用,可以簡單地返回異步函數(shù)的 Promise 對象,而不是在調(diào)用者處添加async/await。然后在需要使用結(jié)果的地方,再使用 async/await 處理。
  • 使用回調(diào)函數(shù):如果不適合使用async/await,可以考慮使用回調(diào)函數(shù)的方式處理異步操作。將異步函數(shù)的回調(diào)函數(shù)傳遞給異步函數(shù),在回調(diào)函數(shù)中處理結(jié)果。

以下是一個簡單的示例,展示了如何將異步操作限制在數(shù)據(jù)訪問層,并使用事件驅(qū)動來解耦代碼:

數(shù)據(jù)訪問層(使用異步操作):

// dataAccessLayer.js
import axios from "axios";

export const fetchData = async (url) => {
  try {
    const response = await axios.get(url);
    return response.data;
  } catch (error) {
    throw new Error(`Error fetching data: ${error.message}`);
  }
};

事件處理器(處理數(shù)據(jù)訪問層的結(jié)果,發(fā)布事件):

// eventHandler.js
import EventEmitter from "events";
import { fetchData } from "./dataAccessLayer";

export const eventEmitter = new EventEmitter();

export const fetchAndEmitData = async (url) => {
  try {
    const data = await fetchData(url);
    eventEmitter.emit("dataFetched", data);
  } catch (error) {
    eventEmitter.emit("dataFetchError", error);
  }
};

主邏輯(訂閱事件,處理事件結(jié)果):

// main.js
import { fetchAndEmitData, eventEmitter } from "./eventHandler";

const onDataFetched = (data) => {
  console.log("Data fetched successfully:", data);
};

const onDataFetchError = (error) => {
  console.error("Data fetch error:", error.message);
};

// 訂閱事件
eventEmitter.on("dataFetched", onDataFetched);
eventEmitter.on("dataFetchError", onDataFetchError);

// 觸發(fā)數(shù)據(jù)請求
fetchAndEmitData("https://api.example.com/data");

在這個示例中,我們將異步操作限制在了dataAccessLayer.js中。eventHandler.js負責(zé)處理這些異步操作的結(jié)果,并發(fā)布相應(yīng)的事件。main.js則訂閱這些事件并處理它們的結(jié)果。這樣,我們在主邏輯中避免了使用async和await,從而降低了代碼復(fù)雜度。

還有一種解決方案很有意思,是利用異常捕獲達成的,對其可行性表示懷疑

async function getUser() {
    return await fetch('./1.json');
}

async function m1() {
    const user = await getUser();
    return user;
}

async function m2() {
    const user = await m1();
    return user;
}
async function m3() {
    const user = await m2();
    return user;
}

async function main() {
    const user = await m3();
    console.log(user);
}

從上面的函數(shù)調(diào)用可以看出來,getUser是異步函數(shù),所有使用和相關(guān)聯(lián)的函數(shù)都必須使用async/await變成異步函數(shù),這樣使用也沒有什么問題,但是在函數(shù)式編程環(huán)境中就不合適了。
本來這些函數(shù)應(yīng)該是一個純函數(shù)的,卻因為異步具有傳染性,導(dǎo)致這些函數(shù)全部變成副作用的了,這在函數(shù)式編程環(huán)境中是很難接受的。

所以如何不去改動這些函數(shù),把這些異步全部去掉呢?變成沒有異步的樣子,從而保持這些函數(shù)的純度。如下:

 function getUser() {
    return fetch('./1.json');
}

 function m1() {
    const user = getUser();
    return user;
}

 function m2() {
    const user = m1();
    return user;
}
 function m3() {
    const user = m2();
    return user;
}

 function main() {
    const user = m3();
    console.log(user);
}

怎么操作呢?getUser調(diào)用了fetch請求,導(dǎo)致了異步的產(chǎn)生。
網(wǎng)絡(luò)傳輸是需要時間的,這個是無法改變的。讓瀏覽器完全阻塞那就卡死了,肯定是行不通的。
目前的函數(shù)調(diào)用流程如下:
js 異步傳染,開發(fā),# Web_前端,前端,async/await,異步傳染性
main->getUser->fetch - -> 等待網(wǎng)絡(luò)請求,請求完成 --> getUser->main

由于fetch需要等待導(dǎo)致所有相關(guān)的函數(shù)都要等待。那么只能在fetch這里做一些操作了。如何讓fetch不等待,就只能報錯了。
js 異步傳染,開發(fā),# Web_前端,前端,async/await,異步傳染性
我們看下通過fetch報錯如何解決這個問題。

main->getUser->fetch->error
拿到結(jié)果存入cache: main->getUser->fetch->cache->getUser->main

在調(diào)用fetch的時候不等待了而是報錯,這樣所有函數(shù)都終止了,調(diào)用棧層層彈出,調(diào)用結(jié)束。

但是我們最終的目的是要拿到結(jié)果的,前面雖然報錯了,網(wǎng)絡(luò)線程仍然還在繼續(xù)網(wǎng)絡(luò)請求它不會停止,直到拿到結(jié)果。

拿到結(jié)果后我們把它放在一個緩存中,接著再去恢復(fù)整個調(diào)用鏈的執(zhí)行。再執(zhí)行fetch時,結(jié)果已經(jīng)緩存在cache了,取出數(shù)據(jù)就可以直接交付不用等待了從而變成了同步函數(shù)。

整個過程會走兩次,第一次以錯誤結(jié)束,第二次以成功結(jié)束,這兩次都是同步的。

在這個過程中fetch的邏輯就發(fā)生了變化:
fetch時要判斷是否有緩存,如果有緩存則返回緩存,如果沒有緩存則發(fā)送真實請求同時拋出錯誤,然后把請求的結(jié)果保存。拋出的錯誤為發(fā)送請求返回的Promise對象,目的是為了在請求完成后再去恢復(fù)調(diào)用。

偽代碼實現(xiàn)如下:

function run(func) {
    let cache = {
        status: 'pending',
        value: null
    };
    const oldFetch = window.fetch;
    window.fetch = function(...args){
        if(cache.status == 'fulfilled'){
            return cache.value;
        }else if(cache.status == 'rejected'){
            //之前的請求有問題
            throw cache.value;
        }else{
            // 1. 發(fā)送真是請求
            const promise = oldFetch(...args)
            .then(res=>{
                cache.status = 'fulfilled';
                cache.value = res;
            }, err=> {
                cache.status = 'rejected';
                cache.value = err;
            });
            // 2. 拋出錯誤
            throw promise;
        }
        
    }
    // 執(zhí)行入口函數(shù)
    try {
        func();
    } catch (error) {
        if(error instanceof Promise) {
            // 不論成功還是失敗都重新調(diào)用
            error.then(func,func).finally(()=>{
                //恢復(fù)原來的值
                window.fetch = oldFetch;
            });
        }
    }
    
}
run(main);

來源

在前端開發(fā)中如何消除異步的傳染性?
消除async/await異步的傳染性
如何解決 async/await 的傳染性?文章來源地址http://www.zghlxwxcb.cn/news/detail-818547.html

到了這里,關(guān)于【前端】淺談async/await異步傳染性的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!

本文來自互聯(lián)網(wǎng)用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務(wù),不擁有所有權(quán),不承擔(dān)相關(guān)法律責(zé)任。如若轉(zhuǎn)載,請注明出處: 如若內(nèi)容造成侵權(quán)/違法違規(guī)/事實不符,請點擊違法舉報進行投訴反饋,一經(jīng)查實,立即刪除!

領(lǐng)支付寶紅包贊助服務(wù)器費用

相關(guān)文章

  • async和await用法理解和快速上手 , 同步任務(wù)和異步任務(wù)順序安排和輕松理解 , js代碼執(zhí)行順序表面知道

    async和await用法理解和快速上手 , 同步任務(wù)和異步任務(wù)順序安排和輕松理解 , js代碼執(zhí)行順序表面知道

    學(xué)習(xí)關(guān)鍵語句 : async , await 用法 await 怎么使用 同步任務(wù)和異步任務(wù) 微任務(wù)和宏任務(wù) js中代碼執(zhí)行順序 雖然說 async 和 await 是 Promise 的語法糖 , 但是用慣了Promise 的人(我) , 還真不能超快速使用上這個語法糖 , 所以趕緊寫一篇文章出來讓各位了解了解這個到底怎么用在我的項目

    2024年02月03日
    瀏覽(48)
  • promise及異步編程async await

    promise及異步編程async await

    ECMAScript 6 新增了正式的 Promise(期約)引用類型,支持優(yōu)雅地定義和組織異步邏輯。接下來幾個版本增加了使用 async 和 await 定義異步函數(shù)的機制 JavaScript 是單線程事件循環(huán)模型。異步行為是為了優(yōu)化因計算量大而時間長的操作,只要你不想為等待某個異步操作而阻塞

    2024年02月04日
    瀏覽(24)
  • HarmonyOS通過async與await同異步轉(zhuǎn)換 解決異步回調(diào)地獄

    HarmonyOS通過async與await同異步轉(zhuǎn)換 解決異步回調(diào)地獄

    我在 HarmonyOS 發(fā)送http網(wǎng)絡(luò)請求 中講述了 HTTP請求的基本方式 然后 就帶出了 回調(diào)地獄的問題 然后 上文 HarmonyOS 通過Promise 解決異步回調(diào)地獄問題 我們用Promise的解決方案 搞定了 這個問題 但是 Promise 這種寫法 可讀性其實沒有那么優(yōu)秀 沒有搞定 Promise return規(guī)則的人甚至都看不懂

    2024年01月24日
    瀏覽(26)
  • 消滅異步回調(diào),還得是 async-await

    關(guān)于異步處理問題,ES5的回調(diào)讓我們陷入回調(diào)地獄輪回,后來ES6的Promise(Promise不了解?點這了解[1])讓我們脫離輪回,終于,ES7的async-await帶我們走向光明。今天我們就來學(xué)習(xí)一夏 async-await,看看與Promise有何聯(lián)系和區(qū)別。 一、走進Async-await原理 1、原理1 async函數(shù)返回一個

    2024年02月10日
    瀏覽(24)
  • 異步編程的概念 以及async和await的工作原理

    一、引言 二、異步編程的基本概念 三、基于任務(wù)的異步模式(TAP) 四、async和await async的工作原理: await的工作原理: 五、異步方法的編寫和調(diào)用 六、異常處理 七、取消異步操作 八、性能考慮 九、案例:異步下載文件 十、結(jié)論 在.NET中,異步編程是一

    2024年04月16日
    瀏覽(44)
  • 微信小程序——異步請求使用async/await實現(xiàn)同步

    微信小程序——異步請求使用async/await實現(xiàn)同步

    ????????在小程序的開發(fā)中,我們知道網(wǎng)絡(luò)請求wx.requset是一個異步請求的API,當(dāng)我們使用它時,會出現(xiàn)請求還沒有結(jié)束,我們下面寫的處理數(shù)據(jù)的代碼就已經(jīng)執(zhí)行了從而導(dǎo)致了我們寫的程序出現(xiàn)問題,那么我們該怎么解決這個問題呢?今天我們用async/await來實現(xiàn)一下吧。

    2024年02月11日
    瀏覽(26)
  • C#異步方法async/await的三種返回類型

    有群友問C#異步方法async返回值Task和void的區(qū)別?看似簡單,但不容易把它們用好。在C#中的異步編程已經(jīng)成為現(xiàn)代編程的標配,異步方法(async/await)是實現(xiàn)異步編程的一種常用方式。在異步方法中,可以使用 Task 或 void 作為返回類型,還可以使用ValueTask返回類型。本文將介紹

    2024年02月04日
    瀏覽(22)
  • Unity 中的 async/await:優(yōu)雅處理異步任務(wù)與協(xié)程

    內(nèi)容將會持續(xù)更新,有錯誤的地方歡迎指正,謝謝! ? Unity 中的 async/await:優(yōu)雅處理異步任務(wù)與協(xié)程Coroutine ? ? ? TechX 堅持將創(chuàng)新的科技帶給世界! 擁有更好的學(xué)習(xí)體驗 —— 不斷努力,不斷進步,不斷探索 TechX —— 心探索、心進?。?助力快速掌握 async/await 異步等待 為初

    2024年02月06日
    瀏覽(32)
  • 深入理解Async/Await:從原理到實踐的JavaScript異步編程指南

    深入理解Async/Await:從原理到實踐的JavaScript異步編程指南

    理解 async/await 的原理和使用方法是理解現(xiàn)代JavaScript異步編程的關(guān)鍵。這里我會提供一個詳細的實例,涵蓋原理、流程、使用方法以及一些注意事項。代碼注釋會盡量詳盡,確保你理解每個步驟。 實例:使用async/await進行異步操作 詳細解釋和注釋: 異步函數(shù)定義: async func

    2024年02月05日
    瀏覽(76)
  • 詳解async 與 await,帶您理解Playwright使用異步方法的正確姿勢!

    詳解async 與 await,帶您理解Playwright使用異步方法的正確姿勢!

    大家在使用python做playwright自動化測試的過程中,一定會發(fā)現(xiàn)下面這種異步用法 很多同學(xué)可能只是按照這種寫法來編寫項目的自動化測試代碼,對于具體細節(jié)可能并不了解,今天我就來講一下playwright異步用法的相關(guān)技術(shù)細節(jié)。建議大家拷貝文檔中的腳本實際運行一下,學(xué)習(xí)的

    2024年02月12日
    瀏覽(30)

覺得文章有用就打賞一下文章作者

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

請作者喝杯咖啡吧~博客贊助

支付寶掃一掃領(lǐng)取紅包,優(yōu)惠每天領(lǐng)

二維碼1

領(lǐng)取紅包

二維碼2

領(lǐng)紅包