Node.js:何时使用Promises vs Callbacks [英] Node.js: When to use Promises vs Callbacks

查看:97
本文介绍了Node.js:何时使用Promises vs Callbacks的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一些要更新的旧Node.js代码.在此过程中,我正在设计新模块以与旧代码一起使用.我发现现在,与我最初写这篇文章时相反,我更多地依赖于使用ES6 Promise,而不是回调.所以现在我混合了一些函数,这些函数返回Promise和一些采用回调-这很乏味.我认为最终应该重构使用诺言.但是在此之前...

I have some older Node.js code that I'm updating. In the process I'm designing new modules to work with the old code. I'm finding that now, as opposed to when I first wrote this, I rely more on using ES6 promises rather than callbacks. So now I have this mix of some functions returning promises and some taking callbacks - which is tedious. I think eventually it should be refactored to use promises. But before that is done...

在什么情况下首选promise和回调在哪里?

What are the situations where promises are preferred and where are callbacks preferred?

在某种情况下,回调能比承诺更好地处理吗,反之亦然?

Is there any type of situation that a callback can handle better than a promise and vice-versa?

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

Based on what I've seen so far, I can't really see any reason to use callbacks instead of promises. Is that true?

推荐答案

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

First off, you pretty much never want to write code that is a mix of callbacks and promises for async operations. If you're moving to promises or introducing some promises, then you probably want to refactor the callbacks in that same section of code into promises. For the appropriate types of operations, there are so many advantages of promises over plain callbacks that it is well worth the effort to convert when already working in an area of code.

承诺非常适合:

  • 监视同步操作
  • 那只需要通知一次(通常是完成或错误)
  • 协调或管理多个异步操作,例如排序或分支异步操作或同时管理飞行中的多个操作
  • 从嵌套或深度嵌套的异步操作传播错误
  • 准备好代码以准备使用异步/等待(或现在与编译器一起使用)
  • 适合Promise模型的操作,其中只有三个状态:pendingfulfilledrejected,并且状态从pending => fulfilled或从pending => rejected转换的状态无法更改(单个-方式过渡.)
  • 动态链接或链接异步操作(例如执行这两个异步操作,检查结果,然后根据中间结果决定要执行哪些其他异步操作)
  • 同时管理异步操作和同步操作
  • 自动捕获并向上传播异步完成回调中发生的任何异常(在普通回调中,这些异常有时会被静默隐藏).
  • Monitoring synchronous operations
  • That need to notify only once (usually completion or error)
  • Coordinating or managing multiple asynchronous operations such as sequencing or branching async operations or managing multiple operations in flight at the same time
  • Propagating errors from nested or deeply nested async operations
  • Getting code ready for the use of async/await (or using it now with a transpiler)
  • Operations that fit the Promise model where there are only three states: pending, fulfilled and rejected and where the state transitions from pending => fulfilled or from pending => rejected can then not change (a single one-way transition).
  • Dynamically linking or chaining asynchronous operations (such as do these two async operations, examine the result, then decide which other async operations to do based on the intermediate result)
  • Managing a mix of asynchronous and synchronous operations
  • Automatically catching and propagating upwards any exceptions that occur in async completion callbacks (in plain callbacks these exceptions are sometimes silently hidden).

简单的回调适用于承诺无法完成的事情:

  • 同步通知(例如Array.prototype.map()的回调)
  • 可能不止一次发生的通知(因此需要多次调用回调).承诺是一次性的设备,不能用于重复通知.
  • 无法映射到未决,已实现,已拒绝的单向状态模型中的情况.
  • Synchronous notifications (such as the callback for Array.prototype.map())
  • Notifications that may occur more than once (and thus need to call the callback more than once). Promises are one-shot devices and cannot be used for repeat notifications.
  • Situations that cannot be mapped into the pending, fulfilled, rejected one-way state model.

而且,我还要在混合中添加EventEmitter.

And, I'd also add EventEmitter to the mix.

事件发射器非常适合:

  • 发布/订阅类型通知
  • 具有事件模型的接口,尤其是在事件可以多次发生(例如流)的情况下
  • 当第三方代码想要参与或监视某些东西而没有EventEmitter的API时,松散耦合.无需设计API.只需公开一个eventEmitter并定义一些事件以及与之相关的数据即可.

有关将纯回调代码转换为Promises的说明

如果您的回调符合作为最后一个参数传递并像callback(err, result)这样调用的回调的节点调用约定,那么您会在node.js中使用util.promisify()在某种程度上自动将父函数包装在promise中,或者使用 Bluebird承诺库,带有

If your callbacks fit the node calling convention with the callback passed as the last argument and called like this callback(err, result), then you somewhat automatically wrap the parent function in a promise with util.promisify() in node.js or if using the Bluebird promise library, with Promise.promisify().

使用Bluebird,您甚至可以一次分配一个完整的模块(在node.js调用约定中使用异步回调),例如:

With Bluebird, you can even promisify an entire module (that uses async callbacks in the node.js calling convention) at once such as:

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的函数.

There is now util.promisify() which will convert an async function that uses the node.js async calling convention to a function that returns a promise.

文档中的示例:

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.
});

这篇关于Node.js:何时使用Promises vs Callbacks的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆