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
Javascript 使用承诺进行顺序处理_Javascript_Node.js_Promise_Es6 Promise_Rsvp.js - Fatal编程技术网

Javascript 使用承诺进行顺序处理

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

我对Node.js和JavaScript比较陌生-如果下面的问题很愚蠢,请原谅。 对我来说,异步处理的承诺是有意义的,但对于串行/顺序处理,我不能100%肯定承诺的使用。让我们看一个示例(伪代码):

目标:读取文件,处理从文件中读取的内容并发送通知 使用HTTP post调用

bendUniverseWithoutPromise: function() {

   var data = fs.readFileSync(..); //Read the file
   var result = processData(data);
   this.postNotification(data);

}
在上面的函数中,processData()在读取文件之前无法运行。在完成处理之前,我们无法发送通知

让我们看一个稍微不同的版本(假设上面的每个方法调用都返回一个承诺,或者我们将它们包装成一个承诺):

现在,我的问题是:

  • 鉴于我们在这种情况下需要串行/顺序处理,承诺版本如何优于非承诺版本?它比第一个例子做得更好的是什么?也许这是一个坏例子,但有什么好例子可以证明这些差异呢
  • 除了语法之外,promise版本在代码可读性方面增加了一点(只有一点),并且可能会因为嵌套的promise、上下文(这!)等而变得非常复杂
  • 我确实理解,从技术上讲,第一种方法在所有处理完成之前不会返回,第二种方法将立即返回,尽管处理仍然是顺序的(在方法的上下文中),但将在后台进行
  • 关于承诺的使用是否有一般规则?有什么模式和反模式吗

  • 提前感谢您。

    首先,让我们更正异步代码:

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