Nodejs 在异步上创建简单队列

2024-04-19

在下面的示例代码中,我可以同时运行多功能

Promise.all([sendMoneyToRequestedUser(_data), saveTransferMoneyTransaction(_data)])
    .then(function (results) {
        log.info("OOOOOOOOOOOOOo");
    }).catch(function (error) {
    log.info(error)
});

但我想为他们创建简单的队列,例如,我可以用Promise用这个解决方案?我有3个功能check, send, and post,我想串联运行并将每个步骤的结果传递给另一个步骤。

Step 1, check()功能,Step 2, send()函数,然后在完成后执行函数,例如post()

对于此实现,我需要获取每个步骤的结果,例如从以下位置获取结果Step 1,如果返回 true 则Step 2我需要使用的结果Step 1,

is async.parallel此实施的解决方案?或者Promise可以这样做


Update:

有一个模块可以做到这一点:https://www.npmjs.com/package/promise-queue https://www.npmjs.com/package/promise-queue

旧答案:

我在尝试使用各种模块时遇到了问题,最后我编写了我能想到的此类工作的最简单的实现。

看看我写的这个简单的类(Plain JS):

class Queue {
    constructor(maxSimultaneously = 1) {
        this.maxSimultaneously = maxSimultaneously;
        this.__active = 0;
        this.__queue = [];
    }
    
    /** @param { () => Promise<T> } func 
     * @template T
     * @returns {Promise<T>}
    */
    async enqueue(func) {
        if(++this.__active > this.maxSimultaneously) {
            await new Promise(resolve => this.__queue.push(resolve));
        }

        try {
            return await func();
        } catch(err) {
            throw err;
        } finally {
            this.__active--;
            if(this.__queue.length) {
                this.__queue.shift()();
            }
        }
    }
}

像这样使用它:

假设您有这个异步函数:

const printNumber = async (n) => {
    await new Promise(res => setTimeout(res, 2000)); // wait 2 sec
    console.log(n);
}

所以,而不是:

await printNumber(1);
await printNumber(2);
await printNumber(3);
await printNumber(4);

use:

const q = new Queue();

q.enqueue(() => printNumber(1));
q.enqueue(() => printNumber(2));
q.enqueue(() => printNumber(3));
q.enqueue(() => printNumber(4));

每个函数将在其他函数完成后执行。

输出:

1 // after 2 sec
2 // after 4 sec
3 // after 6 sec
4 // after 8 sec

或者您可以限制队列同时运行一定数量的函数:

const q = new Queue(3);

q.enqueue(() => printNumber(1));
q.enqueue(() => printNumber(2));
q.enqueue(() => printNumber(3));
q.enqueue(() => printNumber(4));

输出:

1 // after 2 sec
2 // after 2 sec
3 // after 2 sec
4 // after 4 sec

Also, enqueue 方法将返回/抛出您的 Promise 中的原始数据!

假设您编写了一个 API 来上传文件,并且希望将同时上传的数量限制为最多 5 个。您希望一切都保持原样,而不改变您的流程。您可以按照以下方法执行此操作:

async function upload(data) {
    // upload...
    if(something) {
        return 200;
    } else {
        throw 400;
    }
}

因此,不要这样做:

async function work(data) { 
    // do something...
    return await upload(data);
}

do this:

const q = new Queue(5); // up to 5 at the same time
async function work(data) { 
    // do something...
    return await q.enqueue(() => upload(data));
}
class Queue {
    constructor(maxSimultaneously = 1) {
        this.maxSimultaneously = maxSimultaneously;
        this.__active = 0;
        this.__queue = [];
    }

    /** @param { () => Promise<T> } func 
     * @template T
     * @returns {Promise<T>}
    */
    async enqueue(func) {
        if(++this.__active > this.maxSimultaneously) {
            await new Promise(resolve => this.__queue.push(resolve));
        }

        try {
            return await func();
        } catch(err) {
            throw err;
        } finally {
            this.__active--;
            if(this.__queue.length) {
                this.__queue.shift()();
            }
        }
    }
}

const printNumber = async (n) => {
    await new Promise(res => setTimeout(res, 2000)); // wait 2 sec
    console.log(n);
}

async function start() {
    console.log('starting...');
    const q = new Queue();
    
    q.enqueue(() => printNumber(1));
    q.enqueue(() => printNumber(2));
    q.enqueue(() => printNumber(3));
    q.enqueue(() => printNumber(4));
}
Click this to run 1 log per 2 sec: <button onclick="start();">Start</button>
class Queue {
    constructor(maxSimultaneously = 1) {
        this.maxSimultaneously = maxSimultaneously;
        this.__active = 0;
        this.__queue = [];
    }

    /** @param { () => Promise<T> } func 
     * @template T
     * @returns {Promise<T>}
    */
    async enqueue(func) {
        if(++this.__active > this.maxSimultaneously) {
            await new Promise(resolve => this.__queue.push(resolve));
        }

        try {
            return await func();
        } catch(err) {
            throw err;
        } finally {
            this.__active--;
            if(this.__queue.length) {
                this.__queue.shift()();
            }
        }
    }
}

const printNumber = async (n) => {
    await new Promise(res => setTimeout(res, 2000)); // wait 2 sec
    console.log(n);
}

async function start() {
    console.log('starting...');
    const q = new Queue(3);
    
    q.enqueue(() => printNumber(1));
    q.enqueue(() => printNumber(2));
    q.enqueue(() => printNumber(3));
    q.enqueue(() => printNumber(4));
}
Click this to run up to 3 logs every 2 sec: <button onclick="start();">Start</button>
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Nodejs 在异步上创建简单队列 的相关文章

  • 我可以将 RegExp 和 Function 存储在 JSON 中吗?

    给定一个像这样的块 var foo regexp http fun function 将其存储在 JSON 中的正确方法是什么 您必须将 RegExp 作为字符串存储在 JSON 对象中 然后您可以从字符串构造一个 RegExp 对象 JS
  • Firebug 说“此页面上没有 Javascript”,即使页面上确实存在 JavaScript

    为什么Firebug说有No Javascript on this page当页面上明显有 JavaScript 负载时 我什至多次重新加载页面以确保但它仍然显示相同的消息 它以前从来没有这样做过 但突然间它就行为不当了 是因为某些配置问题
  • Electron 应用程序可以与 java 代码集成吗?

    由于node js仍然缺乏Java中存在的重要功能 因此我想使用Java而不是node js 并使用Web语言 html js css 创建客户端 Electron 是跨平台的 java 也是跨平台的 因此似乎有一个能够两全其美的解决方案
  • 表单验证后 isValid 保持 false

    我有一个自定义验证函数 但即使它没有返回错误 表单仍然无效 我将以下属性传递给 Formik validate import files gt return import files values length 0 import files
  • Momentjs 时区 - 获取特定时区时间的日期

    我正在尝试根据用户特定时区的 UTC 基准 创建日期 在本例中使用 momentjs momentjs 时区的 美国 洛杉矶 但是 我没有得到我期望的结果 var tempDate moment 1448841600000 moment 2
  • Express.js req.ip 正在返回 ::ffff:127.0.0.1

    我目前正在尝试获取所请求用户的IP 问题是IP正在返回 ffff 127 0 0 1代替127 0 0 1 我尝试使用trusted proxy选项 尽管不使用代理 和req ips是空白的 使用 4 x Express js router
  • 在 VueJs 中使用上下键自动完成搜索

    除了自动完成搜索之外 我还想添加功能以允许使用 VueJs 按下 向上键功能 我的模板如下所示 div h2 Todos h2 div class autocomplete div div
  • 如何修复 Eslint 错误“prefer-destructuring”?

    我想像这样缩短 ES6 中的对象文字 const loc this props local 原因是loc foo 比打字容易得多this props local foo 但现在 ESLint 抱怨道 使用对象解构 prefer destru
  • Javascript:如何简化具有多个 OR 条件的 if 语句?

    很抱歉 如果我在写这篇文章时犯了错误 我是新来的 不知道这是如何工作的 希望我能尽快学会 我也是 JavaScript 新手 所以问题是 我有这个代码 elements js文件 我无法让它工作 放这个有用吗 if codePrompt c
  • 这个作用域/闭包什么时候在 javaScript 中被垃圾回收?

    我正在做一门课程 该课程正在讨论范围 闭包并简要提到垃圾收集 课程中提出一个问题 范围保持多久 答案是 直到 不再有任何提及它 是的 所以我们基本上说的是 是的 闭包有点像对隐藏范围对象的引用 所以只要有一些函数仍然有一个闭包 范围 该范围
  • 将 viewbag 转换为 javascript 数组

    我想将数据从 ViewBag mytags 获取到 Javascript 数组 但我无法执行此操作 function var sampleTags new Array var array Html Raw Json Encode ViewB
  • 如何使用 JavaScript 或 jQuery 获取 html 元素的比例值?

    我想知道如何获得元素的比例值 我努力了 element css webkit transform 返回matrix scaleX 0 0 scaleY 0 0 有没有办法得到scaleX and scaleY only 找出文档和元素之间的
  • 如何在 jQuery 中使用其中心作为参考点来缩小 div?

    我有以下 div div style margin left 0px height 100px width 100px background color red div 我想使用 jQueryanimate 将 div 缩小到其大小的一半
  • TinyMCE 选择文本并使用 javascript 激活链接对话

    我正在尝试编写一个自动化 使用黄瓜 水豚 硒 测试 它将在tinymce框中选择一些文本 单击链接按钮 然后打开链接选择页面 但链接按钮仅在选择某些文本时才变为活动状态 所以第一轮 tinyMCE activeEditor selectio
  • 如何在Azure上运行nodejs、express js项目的启动命令?

    我在用Azure 开发运营对于我的应用程序 我不确定如何为该项目设置启动命令 如果我将它添加到创建的管道中的任务中 它会给出一个错误 也许是因为该过程永远不会结束 实际上 我可以运行 npm install 并创建工件 但我需要应用程序启动
  • vue中有自动更新这段代码的东西吗?

    我在导航器中找到了这个按钮 当用户登录时会显示该按钮 而当用户注销时该按钮就会消失 但现在我需要在按钮删除 出现之前刷新页面 这是我的代码 Button div div class div div
  • JavaScript 从 json 迭代键和值? [复制]

    这个问题在这里已经有答案了 我正在尝试迭代以下 json VERSION 2006 10 27 a JOBNAME EXEC JOBHOST Test LSFQUEUE 45 LSFLIMIT 2006 10 27 NEWUSER 3 NE
  • 如何暂时停止标题属性显示工具提示?

    我在右键单击时显示了一个弹出 div 我知道这会破坏预期的功能 但 Google 文档会这样做 所以为什么不呢 但是 我在弹出窗口上显示的元素有一个 标题 属性集 该属性集出现在我的分区 我仍然希望工具提示能够工作 但当弹出窗口出现时就不行
  • 哪个 SVG/SMIL DOM 元素具有“beginElement”方法?

    最终 这是针对将在 Firefox 中运行的 Kiosk 风格的应用程序 使用 jQuery 1 6 4 因此答案可能是特定于 Firefox 的 我正在尝试制作动画 SVG 但我正在尝试通过动态插入 SMIL 来为其设置动画 我没有看到任
  • 定位分离的 DOM 树内存泄漏

    我在诊断主要使用 Knockout 构建的非常大的单页 Web 应用程序中的分离 DOM 树内存泄漏时遇到问题 我已经调整了应用程序以附加一个假人FooBar对象特定的 HTML 按钮元素 当用户移动到应用程序的不同 页面 时 该元素应该被

随机推荐

  • 流星合并同一集合的光标

    在我的社交应用程序 如 FB 中 我有一个奇怪的需要 将同一集合用户的两个光标合并到一个发布中 Meteor 服务器打印此错误 发布函数为集合用户返回了多个游标 也许这在 Meteor 0 7 2 中无法完成 也许我的方法是错误的 但我发现
  • 如何在Python中获取Linux控制台窗口宽度

    python 有没有办法以编程方式确定控制台的宽度 我的意思是一行中不换行的字符数 而不是窗口的像素宽度 Edit 寻找适用于 Linux 的解决方案 不确定为什么它在模块中shutil 但它在 Python 3 3 中出现了 看 查询输出
  • 如何在 java 类方法或构造函数中插入前提条件?

    这是我正在上的 Java 课程 本书提到了前置条件和后置条件 但没有给出任何如何对其进行编码的示例 它继续讨论断言 我已经把它记下来了 但是我正在做的作业特别指出插入前提条件并用断言测试前提条件 任何帮助都会很棒 像 Eiffel 这样的语
  • 使用独立对齐和附加的 Listview 元素反应本机 Listview 网格布局

    我有一个关于 Listview 元素对齐的问题 这些元素应该以比行样式更盒装的样式显示 在图片中 您可以看到当前状态 这是通过使用 Listview 的 contentContainerStyle prop 中使用的样式表代码生成的 Lis
  • 带有默认参数的 Swift 选择器

    我在这里编写简单的代码 self navigationItem leftBarButtonItem UIBarButtonItem barButtonSystemItem UIBarButtonSystemItem Cancel targe
  • 使用 RabbitMq 锁定和批量获取消息

    我正在尝试以一种更非常规的方式使用 RabbitMq 尽管此时我可以根据需要选择任何其他消息队列实现 消费者不会将 Rabbit 推送消息留给我的消费者 而是连接到一个队列并获取一批 N 条消息 在此期间它会消费一些消息 并可能拒绝一些消息
  • System.DllNotFoundException:> gtk\bin\libgobject-2.0-0.dll

    我已经构建了一个 GUIGithub https github com saigkill PublicanCreators blob master src PublicanCreators Program cs 启动构建的解决方案后 我得到
  • 如何声明 RSpec 中示例之间共享的变量?

    假设我有以下规格 describe Thing do it can read data do data get data from file 42 36 expect data count to eq 2 end it can proces
  • PHP代码没有被执行,但是代码显示在浏览器源代码中

    我正在尝试在项目上执行一些 PHP 代码 使用 Dreamweaver 但代码未运行 当我检查源代码时 PHP代码显示为HTML标签 我可以在源代码中看到它 Apache 运行正常 我正在使用 XAMPP PHP 页面可以正确打开 但 PH
  • 即使其中一项作业失败,如何将 azure devops 管道结果设置为成功

    我正在开发一个 Azure CD YAML 管道 以将 CI 管道的结果部署到虚拟机上 现在 出于本文的目的 稍微简化一下 CD 管道非常简单 由一个包含 3 个作业的阶段组成 第一个作业运行脚本来停止某种复杂的应用程序 这有时会失败 仅当
  • 当我调试和单步执行时,如何阻止 Xcode 显示该汇编语言?

    我未选中 显示反汇编 但经过几步后 它仍然显示 这可能是使用发布配置而不是调试配置编译的代码 在这种情况下 Xcode 将机器指令与源代码行关联起来会更加困难
  • 我可以使用单个 websocket 服务器同时打开 2 个端口吗

    我是 websocket 编程的新手 目前我正在开发一个简单的 websocket 服务器 使用 c 可以响应 websocket 客户端 我设法在单个端口上使用 1 个客户端和 1 个服务器 我想知道是否可以打开 2 个端口 以便不同的客
  • 获取两个字典列表之间的差异(增量)

    我有以下 Python 数据结构 data1 name u String 1 name u String 2 data2 name u String 1 name u String 2 name u String 3 我正在寻找获得两个列表
  • DataGridTemplateColumn 中的 ComboBox 不显示 SelectedItem

    我想制作其中包含 ComboBox 的自定义 DataGrid 列 组合框的 ItemSource 绑定到枚举 组合框的 selecteditem 绑定到集合元素中选定的枚举值 这是代码
  • 保持java套接字打开?

    我正在制作一个会自动更新的程序 游戏 我有更新部分 但没有检查版本 我本以为这会很容易 这就是我所做的 我为游戏编写了一个更新程序 并且编写了一个服务器 每次客户端 更新程序连接时 服务器都会启动一个线程 线程处理一切 游戏更新程序读取一个
  • Symfony 2 功能测试外部 URL

    无论我做什么 我总能得到一个 Symfony Component HttpKernel Exception NotFoundHttpException 否 已找到 的路线 in crawler gt text 当我尝试使用以下命令请求外部
  • 如何向 img 标签添加到期日期?

    我正在使用 Page Speed Firebug 扩展来帮助提高页面性能 我有一个包含大量图像的页面 它提出的建议之一是 利用浏览器缓存 以下可缓存资源的新鲜生命周期较短 指定以下资源至少在未来一周后到期 http www mysite c
  • 使用Jquery打印div内容

    我想使用 jQuery 打印 div 的内容 这个问题已经在 SO 中提出 但我找不到正确的 有效的 答案 这是我的 HTML div p This is a sample text for printing purpose p div
  • PostgreSQL 恢复后,我收到“关系 django_session 的权限被拒绝”

    我目前正在实时服务器和本地运行我的 Django 1 1 1 站点和 PostgreSQL 8 4 2 当我尝试从本地机器上的实时服务器恢复我的备份之一时 在本地访问我的站点时出现以下错误 http 本地主机 8000 http local
  • Nodejs 在异步上创建简单队列

    在下面的示例代码中 我可以同时运行多功能 Promise all sendMoneyToRequestedUser data saveTransferMoneyTransaction data then function results l