为什么新的 JavaScript 模块请求是同步的?它应该只用于作业队列吗?
有没有办法在 ArangoDB 中发出异步 http(s) 请求?
全面披露:我是 ArangoDB 开发团队的一员,主要从事 Foxx 和所有 JavaScript 方面的工作。我也是编写org/arangodb/request
模块的人。
ArangoDB 是与 Node.js 不同的环境,尽管有许多相似之处(例如使用 V8 JavaScript 引擎)。与 Node.js(或浏览器)不同,ArangoDB 使用基于线程的并发模型并且没有事件循环。然而,线程并没有在 JavaScript 中公开(事实上,在 V8 中,每个线程都是完全隔离的),所以您通常甚至不必考虑它们。
在浏览器和 Node.js 中,功能类似于setTimeout
通过事件循环延迟代码执行(直到经过一定时间或直到发生外部事件)。
在 ArangoDB 中,代码总是线性执行。例如,传入的 HTTP 请求在 JavaScript 中传递给 Foxx 控制器,并在控制器返回后立即发送响应。即使您可以使用setTimeout
,您正在使用的外部资源(甚至是“内部”资源,如文档集合和事务)也可能在延迟代码执行时已经消失。
正因为如此,模块request
提供的功能org/arangodb/request
也是完全同步的。它不返回承诺或接受回调,而是直接返回传入的响应数据。它也绝对不是与 npm 上的相同模块,request
而是基于该模块的 API 的同步实现,以至于在 Node.js 之外实现其 API 是可能的(例如,不包括流和返回远程响应而不是回调)。
如果你来自 Node.js/io.js 背景,这可能会感觉不对,因为非阻塞 IO 可以实现更高的吞吐量,但请记住,ArangoDB 和 Node.js 的设计目标非常不同。Node.js 是围绕流和网络连接构建的。ArangoDB 是作为持久数据存储构建的,必须处理事务和锁。
如果您很可能会出现严重的网络延迟,或者如果外部 API 的响应对客户端响应不是必需的,那么直接从 Foxx 控制器访问外部 API 可能不是最好的主意。这就是 Foxx 队列的用途。事务性电子邮件就是一个很好的例子。
尽管 Foxx 非常通用,但它的主要重点是允许您将大部分应用程序(尤其是从靠近数据运行中受益的逻辑)直接移动到数据库中。对于中小型项目,您可能可以避免在边界内进行外部 API 调用。但是,如果您的应用程序主要关注通过网络与其他服务通信,那么在数据库中运行该代码可能不是最佳解决方案。
幸运的是,ArangoDB 与其他数据库配合得很好,因此如果您发现它在更高负载下成为性能瓶颈,很容易将您的网络密集型代码移出 Foxx。Foxx 并没有消除对应用程序服务器的需求,但它可以大大降低它们的复杂性。
作为对布赖恩回答的更正:可悲的是,承诺也不会让您在同步环境中编写异步代码。Promises/A+ 规范将Promises定义为必须异步执行。在原生不支持它们的地方,它们仍然必须构建在现有函数之上,比如setTimeout
or process.nextTick
,ArangoDB 都没有实现这些函数。