ICode9

精准搜索请尝试: 精确搜索
首页 > 编程语言> 文章详细

如何在 Node 中使用各种异步模式与数据库交互

2023-07-21 13:27:24  阅读:308  来源: 互联网

标签:Node JavaScript 数据库


JavaScript 有一个语句。这部分很简单:运行一些代码并捕获异常,以便可以优雅地处理它们。但是我们为什么需要?提供一种运行清理代码的方法,无论 OR 块中是否引发异常。清理代码通常包括关闭文件句柄和数据库连接。try…catch…finallytry…catchfinallyfinallytrycatch

下面是一个示例:

1
try {

2
  console.log('try 1');

3
  throw new Error('foo');

4
  console.log('try 2');

5
} catch (err) {

6
  console.log('catch 1', err);

7
  throw new Error('bar');

8
  console.log('catch 2');

9
} finally {

10
  console.log('finally!');

11
}

如果您在浏览器控制台(或 Node.js 中运行它),您应该在控制台中看到如下所示的内容:

1
try 1

2
catch 1 Error: foo

3
    at <anonymous>:3:9

4
finally!

5
Uncaught Error: bar

6
    at <anonymous>:7:9

请注意,块中引发的异常最终会作为未经处理的异常冒泡,但不是在执行块之前。barcatchfinally

如果我们在 Node.js 中运行的所有代码都是同步的,我们将能够执行以下操作:

1
try {

2
  // get a connection to the DB

3
  // use the connection to do work

4
} catch (error) {

5
  // handle the error

6
} finally {

7
  // close the connection

8
}

不幸的是,它对异步代码不是很有用—— 至少在异步函数可用之前是这样。原因与 Node.js 中异步工作的方式有关。try…catch…finally

异步/事件处理

下面概述了如何执行异步操作,例如发出 HTTP 请求和执行数据库查询。

 

你所有的JavaScript代码都在主线程上运行。异步 API 从主线程和传递的回调函数调用。根据类型,异步工作可能会完全发生,或者可能会利用线程池。异步工作完成后,回调函数将添加到回调队列中,以尽快在主线程上调用。

使用此体系结构,异步处理期间发生的错误将返回到完全不同的调用堆栈中的主线程。您无法捕获不同调用堆栈中引发的错误 - 为时已晚!

下面是调用异步 API 的一个非常简单的演示:

1
setTimeout(function() {

2
  console.log('hello');

3
}, 2000);

4

5
console.log('world');

如果在浏览器控制台或 Node.js 中运行该脚本,则输出将为:

1
world

2
hello

在“hello”之前两秒看到“世界”可能会让异步编程新手感到惊讶。使其工作的秘诀是传递给 的回调函数。它将“回调”,或者在指定的时间过后在主线程上执行。setTimeout

回调函数可以追溯到 JavaScript 的起源,JavaScript 被设计为一种为网络带来生命的语言。JavaScript 开发人员需要一种将代码与事件相关联的方法,例如加载页面、单击鼠标或按下键盘上的键。随着时间的推移,引入了如下 DOM API。

1
window.addEventListener('load', function() {

2
  // do some work

3
});

上面的方法将传入的匿名函数作为第二个参数,并将其添加到与元素上的事件相关的侦听器列表中。事件发生时,所有侦听器都会添加到回调队列中,并会尽快被调用。addEventListenerloadwindow

为了使回调正常工作,JavaScript 中的函数需要一些重要的特性:它们需要是一等对象,并且需要闭包。

功能一流

函数作为第一类对象的概念听起来比实际更复杂。大多数编程语言都提供了一种声明变量和创建命名代码单元(通常称为函数或过程)的方法。这两种构造之间通常有明显的区别。例如,可以声明变量并将其传递给函数,但不能将函数传递到函数中。

另一方面,JavaScript允许函数更像标准数据类型,如数字,字符串和布尔值。函数可以声明,从一个函数传递到另一个函数,并在将来的某个时候调用。将函数视为一类对象是将回调函数传递到另一个函数的先决条件,但该功能也有助于代码组织。

假设您希望在加载页面和用户单击窗口时执行相同的代码。你可以做这样的事情:

1
window.addEventListener('load', function() {

2
  // do some work

3
});

4

5
window.addEventListener('click', function() {

6
  // do the same work here

7
});

上面代码的问题在于,我们必须维护两个执行相同工作的函数。但是,知道函数是一等对象,我们可以声明一个命名函数,并根据需要传递对它的引用:

1
function doWork() {

2
  // do some work

3
}

4

5
window.addEventListener('load', doWork);

6
window.addEventListener('click', doWork);

如您所见,函数作为一类对象是 JavaScript 的一个简单但强大的功能。

功能提供闭合

闭包的概念一开始可能有点难以理解——但它对于异步/事件编程至关重要。简而言之,闭包是一个函数,它引用在其封闭作用域中定义的变量。

许多语言允许开发人员在函数中嵌套函数,子函数可以引用在父函数的作用域中声明的变量。使用其他语言的开发人员可能永远不会想,“如果在父函数完成执行后运行时调用子函数,会发生什么情况?这根本不可能。但 JavaScript 并非如此!

请记住,JavaScript 中的函数是一等对象,因此与分配给变量的任何其他值一样,它们可以通过传递来摆脱父函数的限制。发生这种情况时,对原始封闭作用域(词法作用域)中的变量的引用仍然存在。那么,将来调用子函数时会发生什么?

闭包可确保只要运行时可能需要调用子函数,子函数就能够访问这些变量。这些变量不会像往常那样被垃圾回收。

下面是一个闭包示例:

1
<html>

2
  <body>

3
    <button id="my-button">Click me!</button>

4

5
    <script>

6
    function onLoad() { // "onLoad" is the parent function.

7
      var button = document.getElementById('my-button');

8

9
      function onClick() { // "onClick" is the child function (closure).

10
        button.parentNode.removeChild(button); // "button" referes to the enslosing scope.

11
      }

12

13
      // "onClick" can be invoked after "onLoad" finishes but the reference to "button"

14
      // will still be valid thanks to closure.

15
      button.addEventListener('click', onClick);

16
    }

17

18
    window.addEventListener('load', onLoad);

19
    </script>

20
  </body>

21
</html>

您可以将此代码复制并粘贴到扩展名为.html的文件中,然后在浏览器中打开它。您应该会看到一个按钮,上面写着“单击我!当窗口加载时,该函数使用按钮上的事件注册函数。onLoadonClickclick

请注意,未在 中调用 。相反,引用被传递给将来可以调用该函数的 API。由于引用在(父)函数中声明的变量,因此闭包可确保将来何时调用该变量。onClickonLoadonClickbuttononLoadonClickbutton

现在我们已经解决了与 JavaScript 中的异步编程相关的一些核心概念,让我们把注意力转向 Node.js 中发展的一些异步模式。

常见异步模式

目前,用于使用 Node 编写异步代码的最常见(和通用)模式.js是回调、异步模块和 promise。Node.js v7.6 对 V8 JavaScript 引擎进行了更新,引入了一种称为异步函数的异步处理新方法。

在为生成器和承诺所做的工作之上,异步函数允许在异步执行时同步编写 JavaScript 代码。最重要的是,循环等同步结构可以按照您的期望工作!异步函数是 JavaScript 的一个重大游戏规则改变者,但对承诺的了解,以及一般的异步处理,仍然很重要。try…catch…finally

我将介绍的每个模式都将有一个专门的帖子。每篇文章都将解释该模式的基础知识,并提供使用该模式的演示应用程序。演示应用将执行相同的三个异步操作:获取与数据库的连接,使用它执行简单查询,然后关闭连接。

要在本地运行演示应用程序,假设已安装 Node.js 和 OCI 客户端库,只需克隆相关的 Gist 或在目录中创建各种文件即可。接下来,在终端中打开目录并运行,然后运行 .npm installnode index.js

提示:如果您想设置本地沙盒来完成这些示例,请参阅此博客文章。

以下是每种模式的链接(随着系列新帖子的发布,链接将变为活动状态):

  • 回调
  • 异步模块
  • 承诺
  • 异步函数

标签:Node,JavaScript,数据库
来源:

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有