NodeJs 異步隊列(AsyncQueue)


原文地址

NodeJs 程序並沒有鎖概念, 可能是單線程程序的緣故吧. 但是存在異步回調, 也就造成並發執行統一代碼的可能性, 當然這里並發不是真正意義上的並發. 是同一線程在不同時間點執行統一代碼. 事故類似代碼如下:

// 阻塞函數
const sleep = async (ms = 0) => {
	return new Promise((resolve, reject) => {
		return setTimeout(resolve(true), ms);
	})
}

let total = 0;
const demoFunc = async () => {
    let count = total;
    await sleep(2000)
    total = count + 1;
}

demoFunc();
demoFunc();
sleep(4000);
console.log(total); // 輸出 1

示例是一個很簡單的自增行為, 很多人可能會說直接在demoFunc()前加 await 不是就是期望結果了, 然后事實可能是真的無法直接這樣做, demoFunc 函數代表其實是一個web請求的處理. total 是數據讀存(db 或 file).
我期望的結果是 2, 實際結果卻為 1. 具體情況不同可能有不同解決方案, 本文提供一種異步隊列機制去順序執行需要互斥的的代碼.

最簡單的互斥執行

只用使用 Promise 鏈執行順序執行互斥代碼.

let queue = Promise.resolve(true);

const queue_exec = async (fn) => {
    queue = queue.then(() => {
        try {
            return Promise.resolve(fn());
        } catch(err) {
            return Promise.reject(err);
        }
    });
    return queue;
}

// 上述示例換成如下調用即可
queue_exec(demoFunc);  // 在實際的請求中可以用 await queue_exec(demoFunc) 或去執行結果.

完善包裝成 NPM 包

上述列表實現過於簡單, 可以做很多優化, 如隊列大小控制, 互斥代碼執行超時, 執行優先級等... 既然實現原理已表明, 錦上添花的功能就不在細化描述, 具體實現參考: AsyncQueue.

假定代碼已經編寫完善, 目錄為 AsyncQueue. 下面記錄發布 NPM 包步驟:

  1. cd AsyncQueue # 進入代碼目錄
  2. npm init # npm 初始化 進入交互模式, 可以一路按回車, 最終生成 package.json 文件
  3. npm login # 登錄 NPM 官網, 交互輸入 npmjs.com 網站的用戶名密碼
  4. 編輯 package.json 修改相關字段
    • name 包名, 不支持大寫, 而且極易與存在的包名沖突, 可以通過 @用戶名/包名 格式做為包名, 避免沖突, 缺點就是包名很長.
    • main 入口文件名, 指定 require(包名) 需要加載到文件名
    • version 包版本
    • 其它字段按需修改即可
  5. 編寫 README.md 文件, 如包安裝 npm install 包名 --save 包介紹, 用法等, 可選.
  6. npm publish --access=public # 發布包, --access=public 顯示發布公開包
  7. 變更完成, 更新 package.json 中 version 字段, 重新發布 npm publish --access=public 即可.


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM