Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/node.js/37.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Node.js:何时使用承诺与回调_Node.js_Callback_Promise_Es6 Promise - Fatal编程技术网

Node.js:何时使用承诺与回调

Node.js:何时使用承诺与回调,node.js,callback,promise,es6-promise,Node.js,Callback,Promise,Es6 Promise,我正在更新一些旧的Node.js代码。在这个过程中,我正在设计新的模块来处理旧代码。我发现现在,与我第一次写这篇文章时不同,我更依赖于使用ES6承诺,而不是回调。所以现在我有一些函数返回承诺,一些函数接受回调,这很无聊。我认为最终它应该被重构以使用承诺。但在这之前 在什么情况下,承诺是首选的,回访是首选的 有没有哪种情况是回调能比承诺更好地处理的,反之亦然 根据我到目前为止所看到的,我真的看不出有任何理由使用回调而不是承诺。这是真的吗?它们的存在都是为了解决同一个问题,处理异步函数的结果 回调往

我正在更新一些旧的Node.js代码。在这个过程中,我正在设计新的模块来处理旧代码。我发现现在,与我第一次写这篇文章时不同,我更依赖于使用ES6承诺,而不是回调。所以现在我有一些函数返回承诺,一些函数接受回调,这很无聊。我认为最终它应该被重构以使用承诺。但在这之前

在什么情况下,承诺是首选的,回访是首选的

有没有哪种情况是回调能比承诺更好地处理的,反之亦然


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

它们的存在都是为了解决同一个问题,处理异步函数的结果

回调往往更加冗长,如果您没有积极地模块化您的函数,那么并发地协调多个异步请求可能会导致错误。错误处理和跟踪往往不那么直截了当,甚至令人困惑,因为可能有许多错误对象,它们都会返回到调用堆栈更深处的单个错误。如果在回调链中使用匿名函数,则在确定原始错误被抛出的位置时,还需要将错误传递回原始调用方,这也可能会导致一些头痛。回调的好处之一是,它们只是简单的旧函数,除了知道异步操作如何工作之外,不需要任何额外的理解

承诺更常见,因为它们需要的代码更少,可读性更强,因为它们像同步函数一样编写,具有单个错误通道,可以处理抛出的错误,并且在最新版本的Node.js中添加后,可以将错误优先回调转换为承诺。现在也有
async/await
,它们还与承诺接口


这完全是基于意见的,因此它实际上是关于您最熟悉的内容,但是,承诺和
async/await
是回调的演变,增强了异步开发体验。无论如何,这并不是一个详尽的比较,而是对回调和承诺的一个高层次的考察。

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

承诺对以下方面很有用:

  • 监视同步操作
  • 只需通知一次(通常为完成或错误)
  • 协调或管理多个异步操作,如排序或分支异步操作,或同时管理多个运行中的操作
  • 从嵌套或深度嵌套的异步操作传播错误
  • 准备好使用async/await的代码(或者现在将其与transpiler一起使用)
  • 符合承诺模型的操作,其中只有三种状态:
    pending
    completed
    rejected
    ,并且状态从
    pending=>completed
    或从
    pending=>rejected
    转换,则不能更改(单个单向转换)
  • 动态链接或链接异步操作(例如执行这两个异步操作,检查结果,然后根据中间结果决定执行哪些其他异步操作)
  • 管理异步和同步操作的混合
  • 自动捕获并向上传播异步完成回调中发生的任何异常(在普通回调中,这些异常有时是隐藏的)
简单的回调对于承诺无法做到的事情是有好处的:

  • 同步通知(例如
    Array.prototype.map()
    的回调)
  • 可能发生多次的通知(因此需要多次调用回调)。承诺是一次性设备,不能用于重复通知
  • 无法映射到挂起、已完成、已拒绝的单向状态模型的情况
而且,我还将添加
EventEmitter

事件发射器非常适合:

  • 发布/订阅类型通知
  • 具有事件模型的接口,特别是当事件可以发生多次时(如流)
  • 当第三方代码想要参与或监视某个东西而不使用任何API(而不是eventEmitter)时,会出现松散耦合。没有API可供设计。只需将eventEmitter公开,并定义一些事件及其附带的数据

关于将普通回调代码转换为承诺的说明

如果回调符合节点调用约定,将回调作为最后一个参数传递,并像这样调用
callback(err,result)
,那么您可以在node.js中使用
util.promisify()
,或者如果使用,则使用

使用Bluebird,您甚至可以一次提交整个模块(在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异步调用约定的异步函数转换为返回承诺的函数

来自


我不记得是从哪里得到这些东西的,但这可能有助于更好地理解承诺

承诺不是收回
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.
});
aAsync()   
.then(bAsync)  
 .then(cAsync)   
.done(finish); 
aAsync(function(){
    return bAsync(function(){
        return cAsync(function(){
            finish()         
        })     
    }) 
}); 
api()
.then(function(result) {   
    return api2(); 
})
.then(function(result2){     
    return api3(); 
})
.then(function(result3){      
    // do work 
})
.catch(function(error) {    
    //handle any error that may occur before this point 
}); 
/* Pretty much the same as a try { ... } catch block. 
Even better: */
api()
.then(function(result){
    return api2(); })
.then(function(result2){
    return api3(); })
.then(function(result3){
    // do work 
})
.catch(function(error) {
    //handle any error that may occur before this point 
})
.then(function() {
    //do something whether there was an error or not      
    //like hiding an spinner if you were performing an AJAX request. 
});
Promise.all([api(), api2(), api3()])
.then(function(result) {
    //do work. result is an array containing the values of the three fulfilled promises. 
})
.catch(function(error) {
    //handle the error. At least one of the promises rejected. 
});