秒速赛车 计划译]理解Nodejs事件驱动机制
秒速赛车技巧-秒速赛车规律_官网-秒速赛车走势图
当前位置:主页 > 秒速赛车技巧 > 正文

秒速赛车 计划译]理解Nodejs事件驱动机制

  学习 Node.js 一定要理解的内容之一,文中主要涉及到了 EventEmitter 的使用和一些异步情况的处理,比较偏基础,值得一读。

  事件驱动机制的最简单形式,是在 Node.js 中十分流行的回调函数,例如 fs.readFile。 在回调函数这种形式中,事件每被触发一次,回调就会被触发一次。

  很久很久以前,在 js 里还没有原生支持 Promise,async/await 还只是一个遥远的梦想,回调函数是处理异步问题的最原始的方式。

  回调从本质上讲是传递给其他函数的函数,在 JavaScript 中函数是第一类对象,这也让回调的存在成为可能。

  一定要搞清楚的是,回调在代码中的并不表示异步调用。 回调既可以是同步调用的,也可以是异步调用的。

  举个例子,这里有一个宿主函数 fileSize,它接受一个回调函数 cb,并且可以通过条件判断来同步或者异步地调用该回调函数:

  这其实也是个反例,这样写经常会引起一些意外的错误,在设计宿主函数的时候,应当尽可能的使用同一种风格,要么始终都是同步的使用回调,要么始终都是异步的。

  我们来研究下一个典型的异步 Node 函数的简单示例,它用回调样式编写:

  readFileAsArray 函数接受两个参数:一个文件路径和一个回调函数。它读取文件内容,将其拆分成行数组,并将该数组作为回调函数的参数传入,调用回调函数。

  现在设计一个用例,假设我们在同一目录中的文件 numbers.txt 包含如下内容:

  如果我们有一个需求,要求统计该文件中的奇数数量,我们可以使用 readFileAsArray 来简化代码:

  这段代码将文件内容读入字符串数组中,回调函数将其解析为数字,并计算奇数的个数。

  这才是最纯粹的 Node 回调风格。回调的第一个参数要遵循错误优先的原则,err 可以为空,我们要将回调作为宿主函数的最后一个参数传递。你应该一直用这种方式这样设计你的函数,因为用户可能会假设。让宿主函数把回调当做其最后一个参数,并让回调函数以一个可能为空的错误对象作为其第一个参数。

  在现代 JavaScript 中,我们有 Promise,Promise 可以用来替代异步 API 的回调。回调函数需要作为宿主函数的一个参数进行传递(多个宿主回调进行嵌套就形成了回调地狱),而且错误和成功都只能在其中进行处理。而 Promise 对象可以让我们分开处理成功和错误,还允许我们链式调用多个异步事件。

  我们在宿主函数的返回值上调用了一个函数来处理我们的需求,这个 .then 函数会把刚刚在回调版本中的那个行数组传递给这里的匿名函数。秒速赛车 计划为了处理错误,我们在结果上添加一个 .catch 调用,当发生错误时,它会捕捉到错误并让我们访问到这个错误。

  在现代 JavaScript 中已经支持了 Promise 对象,因此我们可以很容易的将其使用在宿主函数之中。下面是支持 Promise 版本的 readFileAsArray 函数(同时支持旧有的回调函数方式):

  当有异常抛出时,我们可以通过向回调函数传递 error 来处理错误,也同样可以使用 Promise 的 reject 函数。每当我们将数据交给回调函数处理时,我们同样也可以用 Promise 的 resolve 函数。

  在这种同时可以使用回调和 Promise 的情况下,我们需要做的唯一一件事情就是为这个回调参数设置默认值,防止在没有传递回调函数参数时,其被执行然后报错的情况。 在这个例子中使用了一个简单的默认空函数:()= {}。

  当需要连续调用异步函数时,使用 Promise 会让你的代码更容易编写。不断的使用回调会让事情变得越来越复杂,最终陷入回调地狱。

  Promise 的出现改善了一点,Generator 的出现又改善了一点。 处理异步问题的最新解决方式是使用 async 函数,它允许我们将异步代码视为同步代码,使其整体上更加可读。

  首先,我们创建了一个 async 函数 就是一个普通的函数声明之前,加了个 async 关键字。在 async 函数内部,我们调用了 readFileAsArray 函数,就像把它的返回值赋值给变量 lines 一样,为了真的拿到 readFileAsArray 处理生成的行数组,我们使用关键字 await。之后,我们继续执行代码,就好像 readFileAsArray 的调用是同步的一样。

  要让代码运行,我们可以直接调用 async 函数。这让我们的代码变得更加简单和易读。为了处理异常,我们需要将异步调用包装在一个 try/catch 语句中。

  有了 async/await 这个特性,我们不必使用任何特殊的API(如 .then 和 .catch )。我们只是把这种函数标记出来,然后使用纯粹的 JavaScript 写代码。

  我们可以把 async/await 这个特性用在支持使用 Promise 处理后续逻辑的函数上。但是,它无法用在只支持回调的异步函数上(例如setTimeout)。

  它的概念其实很简单:emitter 对象会发出被定义过的事件,导致之前注册的所有监听该事件的函数被调用。所以,emitter 对象基本上有两个主要特征:

  在这些 emitter 对象的生命周期里,我们可以调用 emit 函数来触发我们想要的触发的任何被命名过的事件。

  emit 函数的使用表示发生某种情况发生了,让大家去做该做的事情。 这种情况通常是某些状态变化引起的。

  我们可以使用 on 方法添加函数,并且每次 emitter 对象触发其关联的事件时,将执行这些函数。

  WithLog 是一个事件触发器,它有一个方法 execute,该方法接受一个参数,即具体要处理的任务函数,并在其前后包裹 log 以输出其执行日志。

  为了看到这里会以什么顺序执行,我们在两个命名的事件上都注册了,最后执行一个简单的任务来触发事件。

  这里我想证实的是以上的输出都是同步发生的,这段代码里没有什么异步的成分。

  跟之前的回调一样,不要一提到事件就认为它是异步的或者同步的,还要具体分析。

  要在异步函数完成后发出事件,我们需要将回调(或 Promise)与基于事件的通信相结合。 下面的例子说明了这一点。

  使用事件而不是常规回调的一个好处是,我们可以通过定义多个对相同的信号做出多个不同的反应。如果使用回调来完成这件事,我们要在单个回调中写更多的处理逻辑。事件是应用程序允许多个外部插件在应用程序核心之上构建功能的好办法。你可以把它们当成钩子来挂一些由于状态变化而引发执行的程序。

  我们传递一个异步的 fs.readFile 函数来测试一下 withTime emitter。 我们现在可以直接通过监听 data 事件来处理读取到的文件数据,而不用把这套处理逻辑写到 fs.readFile 的回调函数中。

  执行这段代码,我们以预期的顺序执行了一系列事件,并且得到异步函数的执行时间,这些是十分重要的。

  请注意,我们是将回调与事件触发器 emitter 相结合实现的这部分功能。 如果 asynFunc 支持Promise,我们可以使用 async/await 函数来做同样的事情:

  我们可以在 emit 函数中不断的添加参数,当然第一个参数一定是事件的名称,除去第一个参数之外的所有参数都可以在该事件注册的中使用。

  例如,要处理 data 事件,我们注册的函数将访问传递给 emit 函数的 data 参数,而这个 data 也正是由 asyncFunc 返回的数据。

  error 事件比较特殊。在我们基于回调的那个示例中,如果不使用处理 error 事件,node 进程将会退出。

  如果我们为这个 error 事件注册一个函数来处理 error,结果将大不相同:

  如果我们执行上述操作,将会报告第一次执行 execute 时发送的错误,但是这次 node 进程不会崩溃退出,其他程序的调用也都能正常完成:

  另一种处理异常的方式是在监听全局的 uncaughtException 进程事件。 然而,使用该事件全局捕获错误并不是一个好办法。

  关于 uncaughtException,一般都会建议你避免使用它,但是如果必须用它,你应该让进程退出:

  但是,假设在同一时间发生多个错误事件,这意味着上面的 uncaughtException 将被多次触发,这可能会引起一些问题。

  EventEmitter 模块暴露了 once 方法,这个方法发出的信号只会调用一次。所以,这个方法常与 uncaughtException 一起使用。

  如果针对一个事件注册多个函数,当事件被触发时,这些函数将按其注册的顺序被触发。

  上述代码会先输出 Length 信息,再输出 Characters 信息,执行的顺序与注册的顺序保持一致。

  如果你想定义一个新的监听函数,但是希望它能够第一个被执行,你还可以使用 prependListener 方法:

  最后,你可以用 removeListener 函数来删除某个函数。

  亚马逊echo火了之后,谷歌微软纷纷入局,在中国,智能音箱已经成为了巨头的游戏。京东、阿里...[详细]

  每日头条、业界资讯、热点资讯、八卦爆料,全天跟踪微博播报。各种爆料、内幕、花边、资讯一网打尽。百万互联网粉丝互动参与,TechWeb官方微博期待您的关注。

版权保护: 本文由 主页 原创,转载请保留链接: http://www.ecentiv.com//html/352.html