在 Node.js 中等待多个回调的惯用方法

2023-12-10

假设您需要执行一些依赖于某些临时文件的操作。自从 我们这里讨论的是 Node,这些操作显然是异步的。 等待所有操作完成的惯用方法是什么 知道什么时候可以删除临时文件吗?

这是一些显示我想要做什么的代码:

do_something(tmp_file_name, function(err) {});
do_something_other(tmp_file_name, function(err) {});
fs.unlink(tmp_file_name);

但是如果我这样写,第三个调用可以在前两个调用之前执行 有机会使用该文件。我需要某种方法来保证前两个 在不嵌套地继续之前调用已经完成(调用它们的回调) 调用(并在实践中使它们同步)。

我考虑过在回调上使用事件发射器并注册一个计数器 作为接收者。计数器将接收已完成的事件并计算有多少 行动仍悬而未决。当最后一个完成后,它将删除 文件。但存在竞争条件的风险,我不确定这是不是 通常这些东西是如何完成的。

Node 人如何解决这种问题呢?


Update:

现在我建议看一下:

  • Promises

    Promise 对象用于延迟和异步计算。 Promise 代表尚未完成但已完成的操作 预计在未来。

    一个流行的 Promise 库是bluebird。 A建议看看为什么要承诺.

    你应该使用承诺来改变这个:

    fs.readFile("file.json", function (err, val) {
        if (err) {
            console.error("unable to read file");
        }
        else {
            try {
                val = JSON.parse(val);
                console.log(val.success);
            }
            catch (e) {
                console.error("invalid json in file");
            }
        }
    });
    

    进入这个:

    fs.readFileAsync("file.json").then(JSON.parse).then(function (val) {
        console.log(val.success);
    })
    .catch(SyntaxError, function (e) {
        console.error("invalid json in file");
    })
    .catch(function (e) {
        console.error("unable to read file");
    });
    
  • 发电机:例如通过co.

    Nodejs 和浏览器基于生成器的控制流优点, 使用 Promise,让您以一种漂亮的方式编写非阻塞代码。

    var co = require('co');
    
    co(function *(){
      // yield any promise
      var result = yield Promise.resolve(true);
    }).catch(onerror);
    
    co(function *(){
      // resolve multiple promises in parallel
      var a = Promise.resolve(1);
      var b = Promise.resolve(2);
      var c = Promise.resolve(3);
      var res = yield [a, b, c];
      console.log(res);
      // => [1, 2, 3]
    }).catch(onerror);
    
    // errors can be try/catched
    co(function *(){
      try {
        yield Promise.reject(new Error('boom'));
      } catch (err) {
        console.error(err.message); // "boom"
     }
    }).catch(onerror);
    
    function onerror(err) {
      // log any uncaught errors
      // co will not throw any errors you do not handle!!!
      // HANDLE ALL YOUR ERRORS!!!
      console.error(err.stack);
    }
    

如果我理解正确的话,我想你应该看看非常好的async图书馆。你应该特别看看series。只是 github 页面片段的副本:

async.series([
    function(callback){
        // do some stuff ...
        callback(null, 'one');
    },
    function(callback){
        // do some more stuff ...
        callback(null, 'two');
    },
],
// optional callback
function(err, results){
    // results is now equal to ['one', 'two']
});


// an example using an object instead of an array
async.series({
    one: function(callback){
        setTimeout(function(){
            callback(null, 1);
        }, 200);
    },
    two: function(callback){
        setTimeout(function(){
            callback(null, 2);
        }, 100);
    },
},
function(err, results) {
    // results is now equals to: {one: 1, two: 2}
});

另外,这个库还可以在浏览器中运行。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

在 Node.js 中等待多个回调的惯用方法 的相关文章

随机推荐

  • 属性不会序列化到 .designer.cs 文件中

    在 VS2010 中 尽管使用 ShouldSerializeFoo 方法 但使用 DesignerSerializationVisibility Visible Content 也不会序列化控件属性 这是代码 class Class1 U
  • 使用或不使用正则表达式提取 YouTube ID

    请告诉我如何在不使用正则表达式的情况下获取youtube ID 使用上述方法以下 URL 没用 http www youtube com e dQw4w9WgXcQ public static String extractYTId Stri
  • 读取 JSF 应用程序内的资源文件

    我需要在 JSF 应用程序中获取资源文件 InputStream input new FileInputStream filename xml 然而系统并没有发现filename xml文件 该文件与以下文件位于同一文件夹中sample x
  • 在 PowerShell 中终止指定用户运行的进程

    如何杀死指定用户运行的所有同名进程 例如 我可以有多个程序 exe由不同的用户运行 我可以使用 get process program exe kill 杀死他们所有人 但我只想杀死指定用户运行的那些实例 有没有方便的方法来做到这一点 V5
  • 如何使用 Node JS (Express) 在 s3 存储桶中一次上传多个图像

    require dotenv config const AWS require aws sdk const multer require multer const multerS3 require multer s3 const uuid
  • WooCommerce 购物车总表时间顺序更改

    How do i add Delivery Fee after Sales Tex 在 Woocommerce 购物车页面中 您需要覆盖模板cart cart totals php 通过主题 所以你必须移动费用块 tr class fee
  • “ret”指令访问冲突

    我有这个函数 它主要由内联汇编组成 long toarrayl int members asm push esp mov eax members imul eax 4 push eax call malloc mov edx eax mov
  • * 和 deref 方法有什么区别? [复制]

    这个问题在这里已经有答案了 例如 我有一个实现了 Deref 的结构 use std ops Deref DerefMut IndexMut derive Debug struct Selector
  • 在嵌套的 Fragment 之间传递数据

    我正在开发一个项目 我必须在片段之间传递数据 所有数据均由我提供DatabaseHandler class SQLiteOpenHelper 我正在手写这篇文章 因此请忽略语法错误 如果有 这是我的Activity看起来像 包含 Selec
  • 将 C++ 函数对象作为线程例程传递给 pthread_create 函数

    我知道传递给 pthread create API 的线程例程具有以下原型 void threadproc void 我只是想知道是否可以使用 C 函数对象作为线程例程 这是我的代码 执行 运行方法需要一个time t变量和一个functo
  • VBA 在特定时间段内从用户创建的文件夹中删除 Outlook 邮件

    我正在寻找一个 VBA 代码片段来删除六 6 个月或更早且位于用户创建的文件夹中的 Outlook 邮件 该代码是什么样的 这是一个示例脚本 Sub DeleteOlderThan6months Dim oFolder As Folder
  • 通过反射传递引用嵌套结构

    type Client struct Id int Age int PrimaryContact Contact Name string type Contact struct Id int ClientId int IsPrimary b
  • 在 Razor 中生成动态 XML

    我在 ASP NET 之外使用 Razor 从模板生成 XML 文档 我有以下代码
  • 使用 iText7 从 PDF 中提取文本。如何提高其性能?

    目前 我使用此代码从矩形 区域 中提取文本 public static class ReaderExtensions public static string ExtractText this PdfPage page Rectangle
  • 如何在 Grails 2.0 中从 war 文件中排除资源?

    我的 Grails 2 应用程序中有一些测试数据 其中包含一些特殊内容 图像 视频等 在构建战争时不应包含这些内容 在开发时 这些文件存储在web app content 那么问题来了 在生产环境构建战争时如何排除它们呢 在我的搜索过程中我
  • 从上下文菜单复制文件的父目录路径

    我正在学习批处理脚本 因为它对于设置 Windows 用户选择的一些快速自定义上下文菜单选项来获取文件及其父目录的路径非常有用 现在我知道以下命令将传递的参数作为文件路径并将其复制到剪贴板 cmd c echo set p 1 clip 但
  • Extjs网格面板一列背景颜色更改另一列值

    我有一个 Extjs 编辑器网格面板 在其中我必须根据另一列值的值更改一列的 css 那么如何做到这一点我无法使用渲染器功能 因为它在 onload 上工作还有其他方式我附加代码吗其中我有性别列和 ID 列 因此当性别列选择男性时 ID 的
  • 更改不同分辨率下的 flexbox-direction

    为什么在低于 800px 的分辨率下 flex direction 不会改变 这些项目仍然在一排 如果我想更改不同分辨率的顺序 也会发生同样的情况 这是 HTML 和 CSS body font weight bold text align
  • LDAPS 未与 PHP 连接

    我在使用 Windows 连接到安全 LDAP 服务器时遇到问题 而且我在网上到处都看到同样的情况 但到目前为止还没有有效的解决方案 我尝试过同时使用 IIS 和 WAMPSERVER 我已将 libeay32 dll 和 ssleay32
  • 在 Node.js 中等待多个回调的惯用方法

    假设您需要执行一些依赖于某些临时文件的操作 自从 我们这里讨论的是 Node 这些操作显然是异步的 等待所有操作完成的惯用方法是什么 知道什么时候可以删除临时文件吗 这是一些显示我想要做什么的代码 do something tmp file