第七色在线视频,2021少妇久久久久久久久久,亚洲欧洲精品成人久久av18,亚洲国产精品特色大片观看完整版,孙宇晨将参加特朗普的晚宴

為了賬號安全,請及時綁定郵箱和手機立即綁定
已解決430363個問題,去搜搜看,總會有你想問的

使用異步數(shù)據(jù)存儲 API 的 JavaScript 事件處理程序導致競爭條件

使用異步數(shù)據(jù)存儲 API 的 JavaScript 事件處理程序導致競爭條件

慕姐4208626 2022-11-11 13:29:55
每次觸發(fā)某些瀏覽器事件時(例如,當瀏覽器選項卡關閉時),我都需要更新一些數(shù)據(jù):chrome.tabs.onRemoved.addListener(async (tabId) => {  let data = await getData(); // async operation  ...                         // modify data   await setData(data);        // async operation});問題是,當多個此類事件觸發(fā)器快速連續(xù)時,異步getData()可能會在事件處理程序的后續(xù)調(diào)用中返回陳舊的結果,然后setData()才有機會在較早的事件中完成,從而導致結果不一致。如果事件處理程序可以同步執(zhí)行,則不會發(fā)生此問題,但getData()兩者setData()都是異步操作。這是比賽條件嗎?處理此類邏輯的推薦模式是什么?- - 更新 - -為了提供更多上下文,getData()并且setData()只是一些 Chrome 存儲 API 的承諾版本:async function getData() {  return new Promise(resolve => {    chrome.storage.local.get(key, function(data) => {      // callback    });  });}async function setData() {  return new Promise(resolve => {    chrome.storage.local.set({ key: value }, function() => {      // callback    });  });}出于可讀性目的,我將 API 調(diào)用包裝在 Promise 中,但我認為無論哪種方式都是異步操作?
查看完整描述

1 回答

?
函數(shù)式編程

TA貢獻1807條經(jīng)驗 獲得超9個贊

getData()對于具有異步 API 的數(shù)據(jù)存儲,您有一個相當經(jīng)典的競爭條件,如果您在數(shù)據(jù)處理中使用異步操作(在和之間),競爭條件會更糟setData()。異步操作允許另一個事件在中間運行你的處理,破壞了你的事件序列的原子性。


以下是如何將傳入的 tabId 放入隊列并確保您一次只處理其中一個事件的想法:


const queue = [];


chrome.tabs.onRemoved.addListener(async (newTabId) => {

    queue.push(newTabId);

    if (queue.length > 1) {

        // already in the middle of processing one of these events

        // just leave the id in the queue, it will get processed later

        return;

    }

    async function run() {

        // we will only ever have one of these "in-flight" at the same time

        try {

            let tabId = queue[0];

            let data = await getData(); // async operation


            ...                         // modify data 


            await setData(data);        // async operation

        } finally {

            queue.shift();              // remove this one from the queue

        }

    }

    while (queue.length) {

        try {

            await run();

        } catch(e) {

            console.log(e);

            // decide what to do if you get an error

        }

    }

});

這可以變得更通用,因此可以在多個地方(每個都有自己的隊列)重復使用,如下所示:


function enqueue(fn) {

    const queue = [];

    return async function(...args) {

        queue.push(args);       // add to end of queue

        if (queue.length > 1) {

            // already processing an item in the queue,

            // leave this new one for later

            return;

        }

        async function run() {

            try {

                const nextArgs = queue[0];  // get oldest item from the queue

                await fn(...nextArgs);      // process this queued item

            } finally {

                queue.shift();              // remove the one we just processed from the queue

            }

        }

        // process all items in the queue

        while (queue.length) {

            try {

                await run();

            } catch(e) {

                console.log(e);

                // decide what to do if you get an error

            }

        }

    }

}


chrome.tabs.onRemoved.addListener(enqueue(async function(tabId) {

    let data = await getData(); // async operation


    ...                         // modify data


    await setData(data);        // async operation

}));


查看完整回答
反對 回復 2022-11-11
  • 1 回答
  • 0 關注
  • 91 瀏覽
慕課專欄
更多

添加回答

舉報

0/150
提交
取消
微信客服

購課補貼
聯(lián)系客服咨詢優(yōu)惠詳情

幫助反饋 APP下載

慕課網(wǎng)APP
您的移動學習伙伴

公眾號

掃描二維碼
關注慕課網(wǎng)微信公眾號