Node.js:何时使用 Promises 与 Callbacks

2024-02-04

我正在更新一些较旧的 Node.js 代码。在此过程中,我正在设计新模块来使用旧代码。我发现现在,与我第一次写这篇文章时相比,我更多地依赖于使用 ES6 承诺而不是回调。所以现在我有一些返回承诺的函数和一些回调函数的组合 - 这是乏味的。我认为最终应该重构为使用承诺。但在此之前...

什么情况下首选 Promise,什么情况下首选回调?

回调是否可以比承诺更好地处理任何类型的情况,反之亦然?

根据我到目前为止所看到的,我真的看不出有任何理由使用回调而不是承诺。真的吗?


首先,您几乎不想编写混合了回调和异步操作承诺的代码。如果您要转向 Promise 或引入一些 Promise,那么您可能希望将同一代码部分中的回调重构为 Promise。对于适当类型的操作,promise 相对于普通回调有很多优点,因此在已经在代码区域中工作时进行转换是非常值得的。

Promise 非常适合:

  • 监控同步操作
  • 只需要通知一次(通常是完成或错误)
  • 协调或管理多个异步操作,例如排序或分支异步操作或同时管理多个正在进行的操作
  • 从嵌套或深度嵌套的异步操作传播错误
  • 准备好使用 async/await 的代码(或者现在通过转译器使用它)
  • 适合 Promise 模型的操作只有三种状态:pending, fulfilled and rejected以及状态从哪里转换pending => fulfilled或来自pending => rejected然后就不能改变(单个单向转换)。
  • 动态链接或链接异步操作(例如执行这两个异步操作,检查结果,然后根据中间结果决定执行哪些其他异步操作)
  • 管理异步和同步操作的混合
  • 自动捕获并向上传播异步完成回调中发生的任何异常(在普通回调中,这些异常有时会默默隐藏)。

普通回调对于 Promise 无法完成的事情很有用:

  • 同步通知(例如回调Array.prototype.map())
  • 可能多次发生的通知(因此需要多次调用回调)。 Promise 是一次性设备,不能用于重复通知。
  • 无法映射到待决、已完成、已拒绝单向状态模型的情况。

而且,我还要补充一点EventEmitter混合。

EventEmitter 非常适合:

  • 发布/订阅类型通知
  • 具有事件模型的接口,特别是当事件可以多次发生时(如流)
  • 当第 3 方代码想要参与或监控某些内容而无需使用 eventEmitter 以外的 API 时,就会出现松散耦合。没有API可供设计。只需公开一个 eventEmitter 并定义一些事件以及与之相关的数据即可。

关于将普通回调代码转换为 Promise 的注意事项

如果您的回调符合节点调用约定,回调作为最后一个参数传递并像这样调用callback(err, result),然后你会自动将父函数包装在一个承诺中util.promisify()在 Node.js 中或者如果使用蓝鸟承诺图书馆 http://bluebirdjs.com/docs/api-reference.html, with Promise.promisify() http://bluebirdjs.com/docs/api/promise.promisify.html.

使用 Bluebird,您甚至可以立即 Promisify 整个模块(在 Node.js 调用约定中使用异步回调),例如:

const Promise = require('bluebird');
const fs = Promise.promisifyAll(require('fs'));

fs.writeFileAsync("file.txt", data).then(() => {
    // done here
}).catch(err => {
    // error here
});

在 Node.js 版本 8+ 中

现在有util.promisify()它将使用 Node.js 异步调用约定的异步函数转换为返回 Promise 的函数。

示例来自the doc: https://nodejs.org/api/util.html#util_util_promisify_original

const util = require('util');
const fs = require('fs');

const stat = util.promisify(fs.stat);

// usage of promisified function
stat('.').then((stats) => {
  // Do something with `stats`
}).catch((error) => {
  // Handle the error.
});
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Node.js:何时使用 Promises 与 Callbacks 的相关文章

  • 解析“流”JSON

    我在浏览器中有一个网格 我想通过 JSON 将数据行发送到网格 但浏览器应该在接收到 JSON 时不断解析它 并在解析时将行添加到网格中 换句话说 在接收到整个 JSON 对象后 不应将行全部添加到网格中 应该在接收到行时将其添加到网格中
  • Node.js:无法从同一网络上的不同设备访问服务器

    注意 还有其他一些人也遇到过类似的问题 但这些问题是通过修复代码中涉及服务器如何侦听的小花絮来解决的 在我看到的示例中 他们将 127 0 0 1 作为参数放在http createServer listen 但是 我没有同样的问题 当我尝
  • 如何重置使用 JavaScript 更改的 CSS 属性?

    我的导航按钮的宽度从 100px 增加到 150px 当鼠标悬停在 nav li hover width 150px 但是使用 javascript 我已经做到了 无论选择哪个选项 宽度都将继续为 150px 当选择每个选项时 它会使其他选
  • jQuery AJAX 调用 Java 方法

    使用 jQuery AJAX 我们可以调用特定的 JAVA 方法 例如从 Action 类 该 Java 方法返回的数据将用于填充一些 HTML 代码 请告诉我是否可以使用 jQuery 轻松完成此操作 就像在 DWR 中一样 此外 对于
  • 使用 JavaScript 使链接保持活动状态并在单击时显示悬停效果

    I am struggling to make this work I d like to make it where if O F is clicked the hover state stays active if another li
  • Socket.io - “套接字 ID”是否被视为敏感信息?

    我正在使用 Node js 和 socket io 实现一个简单的聊天应用程序 想知道在整个对象中共享所有客户端的套接字 ID 是否被认为是一个好的做法 为了解释一下 我的每个用户都是这样表示的 nick John Doe dateJoin
  • 如何防止 Iframe 在与浏览器交互后弄乱浏览器的历史记录?

    因此 就我而言 我使用 Iframe 将 Grafana 附加到我的页面 这为我提供了漂亮且易于使用的图表 可以注意到 每次在图表上进行放大或缩小 使用鼠标单击 交互后 Grafana 的 Iframe 都会在我的 Angular 页面上触
  • 在 Wordpress 站点中进行 AJAX 调用时出现问题

    我在使用 Wordpress 站点功能的 AJAX 部分时遇到了一些问题 该功能接受在表单上输入的邮政编码 使用 PHP 函数来查找邮政编码是否引用特定位置并返回到该位置的永久链接 我的第一个问题是关于我构建的表单 现在我的表单操作是空白的
  • Google App Engine:修改云运行环境

    我正在尝试部署一个使用自定义 Node js 服务器的 Next js 应用程序 我想将自定义构建变量注入应用程序 next config js const NODE ENV process env NODE ENV const envTy
  • 标签获取 href 值

    我有以下 html div class threeimages a img alt Australia src Images Services 20button tcm7 9688 gif a div class text h2 a hre
  • 在requestAnimationFrame中使用clearRect不显示动画

    我正在尝试在 HTML5 画布上做一个简单的 javascript 动画 现在我的画布是分层的 这样当我收到鼠标事件时 背景层不会改变 但带有头像的顶层会移动 如果我使用 requestAnimationFrame 并且不清除屏幕 我会看到
  • Meteor - 从客户端取消服务器方法

    我正在通过服务器方法执行数据库计数 用户可以选择他们希望如何执行计数 然后调用该方法 我的问题是 计数可能需要一些时间 并且用户可能会在方法运行时改变主意并请求不同的计数 有什么方法可以取消调用的方法并运行新的计数吗 我认为 this un
  • 如何在react-native中获取Text组件的onPress值

    我是一名新的 React Native 开发人员 我想使用 onPress 获取 Text 组件的值并将其传递给函数
  • aws - 将字符串作为文件上传到 S3 存储桶

    我尝试使用适用于 NodeJS 的 AWS 开发工具包将字符串作为文件保存到 AWS S3 存储桶 PUT 请求成功 但文件未在 S3 存储桶中创建 以下是我的代码片段 const s3 new S3 apiVersion 2006 03
  • 如何在机器人框架中的两条消息之间设置延迟 - Node.js

    我正在开发一个机器人 它使用 botbuilder JS V4 使用 Direct Line 连接到我们的客户端应用程序 由于某些原因 消息以错误的顺序发送给机器人 例如 用户 你好 机器人 我能帮你什么忙吗 机器人 嗨 我是机器人 作为解
  • 稍后解决承诺

    我想构建一个 Promise 但将解决方案推迟到以后 下面的代码创建了一个承诺 但它立即得到解决 我如何控制承诺何时被评估 var p new Promise resolve reject gt resolve 1 then p1 gt c
  • 为 illustrator 导出脚本以保存为 web jpg

    任何人都可以帮我为 illustrator CC2017 编写一个脚本 将文件以 JPG 格式导出到网络 旧版 然后保存文件并关闭 我有 700 个文件 每个文件有 2 个画板 单击 文件 gt 导出 gt 另存为 Web 旧版 然后右键文
  • 如何获取给定 DOM 元素的所有定义的 CSS 选择器?

    如何使用 jQuery 获取给定 DOM 元素的所有定义的 CSS 选择器 定义后 我的意思是在应用于任何样式表的所有 CSS 选择器document 在某种程度上 这类似于 FireBug 实现的功能 其中显示所选 DOM 元素的所有应用
  • 为什么 jquery 没有检测到单选按钮未被选中的情况? [复制]

    这个问题在这里已经有答案了 可能的重复 JQuery radioButton change 在取消选择期间不会触发 https stackoverflow com questions 5176803 jquery radiobutton c
  • 在 React.js 中编辑丰富的数据结构

    我正在尝试为数据结构创建一个简单的基于网格的编辑器 但我在使用 React js 时遇到了一些概念问题 他们的文档对此没有太大帮助 所以我希望这里有人可以提供帮助 首先 将状态从外部组件传输到内部组件的正确方法是什么 是否有可能将内部组件中

随机推荐