Javascript 使用承诺进行顺序处理
我对Node.js和JavaScript比较陌生-如果下面的问题很愚蠢,请原谅。 对我来说,异步处理的承诺是有意义的,但对于串行/顺序处理,我不能100%肯定承诺的使用。让我们看一个示例(伪代码): 目标:读取文件,处理从文件中读取的内容并发送通知 使用HTTP post调用Javascript 使用承诺进行顺序处理,javascript,node.js,promise,es6-promise,rsvp.js,Javascript,Node.js,Promise,Es6 Promise,Rsvp.js,我对Node.js和JavaScript比较陌生-如果下面的问题很愚蠢,请原谅。 对我来说,异步处理的承诺是有意义的,但对于串行/顺序处理,我不能100%肯定承诺的使用。让我们看一个示例(伪代码): 目标:读取文件,处理从文件中读取的内容并发送通知 使用HTTP post调用 bendUniverseWithoutPromise: function() { var data = fs.readFileSync(..); //Read the file var result = pr
bendUniverseWithoutPromise: function() {
var data = fs.readFileSync(..); //Read the file
var result = processData(data);
this.postNotification(data);
}
在上面的函数中,processData()在读取文件之前无法运行。在完成处理之前,我们无法发送通知
让我们看一个稍微不同的版本(假设上面的每个方法调用都返回一个承诺,或者我们将它们包装成一个承诺):
现在,我的问题是:
提前感谢您。首先,让我们更正异步代码:
bendUniverseWithPromise: function() {
return fs.readFileAsync(fileName)
.then(processData)
.then(postNotification);
}
现在,上面的内容(几乎,如果它是完整的话)是一个反模式的东西
至于为什么要使用承诺的版本,它是异步的
.. 它允许在等待异步(主要是I/O)操作时执行其他操作
注意:
fs.readFileAsync
默认情况下不返回承诺,需要“承诺”。我将通过进一步举例来尝试回答您的所有四点
假设第一个操作(文件读取)是一个缓慢的I/O绑定操作,需要900毫秒。处理和通知分别是CPU绑定和I/O绑定,每个操作需要50毫秒
现在,两个版本都需要相同的1000毫秒才能完成,但是第二个示例更好地利用了可用资源,因为它是异步的。这就是基于承诺的版本的优势所在。第一个版本会使服务器在整整一秒钟内完全无响应,而第二个版本只会使服务器在50毫秒CPU限制的处理步骤中无响应
当我们考虑到这些请求中的10个同时到来时,这希望变得更加清晰。第一个示例一次处理一个请求,在1s后处理请求#1,在2s后处理请求#2,依此类推,在10s后完成。其平均性能为1req/s。第二个版本将开始读取请求#1的文件,然后立即继续读取请求#2,旋转另一个文件读取,依此类推所有请求。所有请求都将在1s左右完成读取,假设开销为100ms,磁盘读取带宽很少或没有饱和。然后,处理将排队,所有请求总共需要500毫秒。最后,我们可以并行发布通知,因为它又是I/O绑定的。在这个理想化的示例中,所有请求将在1.5秒内以超过6个请求/秒的速度完成,性能提高了6倍。这完全是由于异步性提供了更好的机智性
因此,规则是,在执行I/O绑定工作时始终使用async/Promissions
旁注: 您的第二个示例不正确,因为该范围中没有定义
数据
或结果
变量,正确的版本将只将函数传递到then()
一个好的规则是,在执行此操作时,可能需要时间,用户会认为我的应用程序没有响应,或者用户可以做其他事情?如果是这样的话,请转到AsyncYou mean
this.postNotification(result)代码>?您可能会发现娱乐我不会称之为显式构造反模式,因为它根本不起作用。此时没有resolve
调用all@Bergi-是的,你是对的。甚至没有注意到它不是真正可用的代码……而且它仍然是不可用的代码,请检查@dape的答案以获得更正的代码段。我想您需要传递this.postNotification.bind(this)
以匹配同步代码
bendUniverseWithPromise: function() {
return fs.readFileAsync(fileName)
.then(processData)
.then(postNotification);
}
bendUniverseWithPromise: function (fileName) {
return fs.readFileAsync(fileName)
.then(processData)
.then(postNotification)
}