Javascript 什么是 Node.js?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/1884724/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-22 21:44:48  来源:igfitidea点击:

What is Node.js?

javascriptnode.jsv8evented-io

提问by Jeff

I don't fully get what Node.jsis all about. Maybe it's because I am mainly a web based business application developer. What is it and what is the use of it?

我不完全了解Node.js的全部内容。也许是因为我主要是基于 Web 的业务应用程序开发人员。它是什么以及它的用途是什么?

My understanding so far is that:

到目前为止,我的理解是:

  1. The programming model is event driven, especially the way it handles I/O.
  2. It uses JavaScriptand the parser is V8.
  3. It can be easily used to create concurrent server applications.
  1. 编程模型是事件驱动的,尤其是它处理I/O 的方式
  2. 它使用JavaScript,解析器是V8
  3. 它可以很容易地用于创建并发服务器应用程序。

Are my understandings correct? If yes, then what are the benefits of evented I/O, is it just more for the concurrency stuff? Also, is the direction of Node.js to become a framework like, JavaScript based (V8 based) programming model?

我的理解正确吗?如果是,那么事件化 I/O 的好处是什么,它只是为了并发性吗?另外,Node.js 的发展方向是像基于 JavaScript(基于 V8)的编程模型那样的框架吗?

采纳答案by postfuturist

I think the advantages are:

我认为优点是:

  1. Web development in a dynamic language (JavaScript) on a VM that is incredibly fast (V8). It is much faster than Ruby, Python, or Perl.

  2. Ability to handle thousands of concurrent connections with minimal overhead on a single process.

  3. JavaScript is perfect for event loops with first class function objects and closures. People already know how to use it this way having used it in the browser to respond to user initiated events.

  4. A lot of people already know JavaScript, even people who do not claim to be programmers. It is arguably the most popular programming language.

  5. Using JavaScript on a web server as well as the browser reduces the impedance mismatch between the two programming environments which can communicate data structures via JSON that work the same on both sides of the equation. Duplicate form validation code can be shared between server and client, etc.

  1. 在速度极快的 VM (V8) 上使用动态语言 (JavaScript) 进行 Web 开发。它比 Ruby、Python 或 Perl 快得多。

  2. 能够在单个进程上以最小的开销处理数千个并发连接。

  3. JavaScript 非常适合具有一流函数对象和闭包的事件循环。人们已经知道如何以这种方式使用它,在浏览器中使用它来响应用户发起的事件。

  4. 很多人已经知道 JavaScript,即使是那些不自称是程序员的人。它可以说是最流行的编程语言。

  5. 在 Web 服务器和浏览器上使用 JavaScript 可以减少两种编程环境之间的阻抗失配,这两种编程环境可以通过 JSON 通信数据结构,在等式的两边工作相同。重复的表单验证代码可以在服务器和客户端等之间共享。

回答by Dave Dopson

I use Node.js at work, and find it to be very powerful. Forced to choose one word to describe Node.js, I'd say "interesting" (which is not a purely positive adjective). The community is vibrant and growing. JavaScript, despite its oddities can be a great language to code in. And you will daily rethink your own understanding of "best practice" and the patterns of well-structured code. There's an enormous energy of ideas flowing into Node.js right now, and working in it exposes you to all this thinking - great mental weightlifting.

我在工作中使用 Node.js,发现它非常强大。被迫选择一个词来描述 Node.js,我会说“有趣”(这不是一个纯粹的积极形容词)。社区充满活力且不断发展。尽管 JavaScript 很奇怪,但它仍然是一种很好的编码语言。您每天都会重新思考自己对“最佳实践”和结构良好代码模式的理解。现在有大量的想法流入 Node.js,在其中工作会让你接触到所有这些想法 - 伟大的精神举重。

Node.js in production is definitely possible, but far from the "turn-key" deployment seemingly promised by the documentation. With Node.js v0.6.x, "cluster" has been integrated into the platform, providing one of the essential building blocks, but my "production.js" script is still ~150 lines of logic to handle stuff like creating the log directory, recycling dead workers, etc. For a "serious" production service, you also need to be prepared to throttle incoming connections and do all the stuff that Apache does for PHP. To be fair, Ruby on Railshas this exactproblem. It is solved via two complementary mechanisms: 1) Putting Ruby on Rails/Node.js behind a dedicated webserver (written in C and tested to hell and back) like Nginx(or Apache/ Lighttd). The webserver can efficiently serve static content, access logging, rewrite URLs, terminate SSL, enforce access rules, and manage multiple sub-services. For requests that hit the actual node service, the webserver proxies the request through. 2) Using a framework like Unicornthat will manage the worker processes, recycle them periodically, etc. I've yet to find a Node.js serving framework that seems fully baked; it may exist, but I haven't found it yet and still use ~150 lines in my hand-rolled "production.js".

生产中的 Node.js 绝对是可能的,但与文档中似乎承诺的“交钥匙”部署相去甚远。在 Node.js v0.6.x 中,“集群”已集成到平台中,提供了基本构建块之一,但我的“production.js”脚本仍然有大约 150 行逻辑来处理诸如创建日志之类的事情目录、回收死去的工人等。对于“严肃”的生产服务,您还需要准备好限制传入的连接并执行 Apache 为PHP所做的所有事情。公平地说,Ruby on Rails有这个确切的问题。它通过两种互补机制解决:1) 将 Ruby on Rails/Node.阿帕奇/ Lighttd)。Web 服务器可以有效地提供静态内容、访问日志记录、重写 URL、终止SSL、执行访问规则和管理多个子服务。对于命中实际节点服务的请求,网络服务器会代理该请求。2)使用像Unicorn这样的框架来管理工作进程,定期回收它们等等。我还没有找到一个看起来完全成熟的 Node.js 服务框架;它可能存在,但我还没有找到它,并且仍然在我手工制作的“production.js”中使用了大约 150 行。

Reading frameworks like Expressmakes it seem like the standard practice is to just serve everything through one Hyman-of-all-trades Node.js service ... "app.use(express.static(__dirname + '/public'))". For lower-load services and development, that's probably fine. But as soon as you try to put big time load on your service and have it run 24/7, you'll quickly discover the motivations that push big sites to have well baked, hardened C-code like Nginxfronting their site and handling all of the static content requests (...until you set up a CDN, like Amazon CloudFront)). For a somewhat humorous and unabashedly negative take on this, see this guy.

阅读像Express这样的框架,似乎标准的做法是通过一个万能的 Node.js 服务来提供一切服务......“app.use(express.static(__dirname + '/public'))” . 对于低负载的服务和开发,这可能没问题。但是,一旦您尝试将大量时间负载在您的服务上并让它 24/7 全天候运行,您就会很快发现推动大型网站拥有完善的、强化的 C 代码(如Nginx位于他们的网站并处理所有内容的动机)静态内容请求(...直到您设置CDN,如Amazon CloudFront))。对于这个有点幽默和毫不掩饰的负面看法,看看这个人

Node.js is also finding more and more non-service uses. Even if you are using something else to serve web content, you might still use Node.js as a build tool, using npmmodules to organize your code, Browserifyto stitch it into a single asset, and uglify-jsto minify it for deployment. For dealing with the web, JavaScript is a perfect impedance matchand frequently that makes it the easiest route of attack. For example, if you want to grovel through a bunch of JSONresponse payloads, you should use my underscore-CLImodule, the utility-belt of structured data.

Node.js 也发现了越来越多的非服务用途。即使您使用其他东西来提供 Web 内容,您仍然可以使用 Node.js 作为构建工具,使用npm模块来组织您的代码,使用Browserify将其拼接成单个资产,并使用uglify-js将其缩小以进行部署. 对于处理 Web 而言,JavaScript 是一种完美的阻抗匹配,并且经常使其成为最简单的攻击途径。例如,如果你想通过一堆JSON响应有效载荷,你应该使用我的underscore-CLI模块,结构化数据的实用程序带。

Pros / Cons:

优点缺点:

  • Pro: For a server guy, writing JavaScript on the backend has been a "gateway drug" to learning modern UI patterns. I no longer dread writing client code.
  • Pro: Tends to encourage proper error checking (err is returned by virtually all callbacks, nagging the programmer to handle it; also, async.js and other libraries handle the "fail if any of these subtasks fails" paradigm much better than typical synchronous code)
  • Pro: Some interesting and normally hard tasks become trivial - like getting status on tasks in flight, communicating between workers, or sharing cache state
  • Pro: Huge community and tons of great libraries based on a solid package manager (npm)
  • Con: JavaScript has no standard library. You get so used to importing functionality that it feels weird when you use JSON.parse or some other build in method that doesn't require adding an npm module. This means that there are five versions of everything. Even the modules included in the Node.js "core" have five more variants should you be unhappy with the default implementation. This leads to rapid evolution, but also some level of confusion.
  • 优点:对于服务器人员来说,在后端编写 JavaScript 是学习现代 UI 模式的“门户药物”。我不再害怕编写客户端代码。
  • 优点:倾向于鼓励正确的错误检查(几乎所有回调都会返回 err,催促程序员处理它;此外,async.js 和其他库处理“如果这些子任务中的任何一个失败则失败”范例比典型的同步代码要好得多)
  • 优点:一些有趣且通常很困难的任务变得微不足道——比如获取正在运行的任务的状态、工作人员之间的通信或共享缓存状态
  • 优点:基于可靠的包管理器 (npm) 的庞大社区和大量优秀库
  • 缺点:JavaScript 没有标准库。您已经习惯于导入功能,以至于在使用 JSON.parse 或其他不需要添加 npm 模块的内置方法时感觉很奇怪。这意味着一切都有五个版本。如果您对默认实现不满意,即使 Node.js“核心”中包含的模块也有五个变体。这导致了快速演变,但也导致了一定程度的混乱。

Versus a simple one-process-per-request model (LAMP):

与简单的每请求一个进程模型 ( LAMP):

  • Pro: Scalable to thousands of active connections. Very fast and very efficient. For a web fleet, this could mean a 10X reduction in the number of boxes required versus PHP or Ruby
  • Pro: Writing parallel patterns is easy. Imagine that you need to fetch three (or N) blobs from Memcached. Do this in PHP ... did you just write code the fetches the first blob, then the second, then the third? Wow, that's slow. There's a special PECLmodule to fix that specific problem for Memcached, but what if you want to fetch some Memcached data in parallel with your database query? In Node.js, because the paradigm is asynchronous, having a web request do multiple things in parallel is very natural.
  • Con: Asynchronous code is fundamentally more complex than synchronous code, and the up-front learning curve can be hard for developers without a solid understanding of what concurrent execution actually means. Still, it's vastly less difficult than writing any kind of multithreaded code with locking.
  • Con: If a compute-intensive request runs for, for example, 100 ms, it will stall processing of other requests that are being handled in the same Node.js process ... AKA, cooperative-multitasking. This can be mitigated with the Web Workers pattern (spinning off a subprocess to deal with the expensive task). Alternatively, you could use a large number of Node.js workers and only let each one handle a single request concurrently (still fairly efficient because there is no process recycle).
  • Con: Running a production system is MUCH more complicated than a CGImodel like Apache + PHP, Perl, Ruby, etc. Unhandled exceptions will bring down the entire process, necessitating logic to restart failed workers (see cluster). Modules with buggy native code can hard-crash the process. Whenever a worker dies, any requests it was handling are dropped, so one buggy API can easily degrade service for other cohosted APIs.
  • 优点:可扩展到数千个活动连接。非常快,非常高效。对于网络队列,这可能意味着与 PHP 或 Ruby 相比,所需的盒子数量减少了 10 倍
  • 优点:编写并行模式很容易。想象一下,您需要从Memcached 中获取三个(或 N 个)blob 。在 PHP 中执行此操作...您是否只编写了获取第一个 blob、第二个和第三个 blob 的代码?哇,这很慢。有一个特殊的PECL模块可以解决 Memcached 的特定问题,但是如果您想与数据库查询并行获取一些 Memcached 数据怎么办?在 Node.js 中,因为范式是异步的,所以让 Web 请求并行执行多项操作是很自然的。
  • 缺点:从根本上说,异步代码比同步代码更复杂,如果开发人员没有深入了解并发执行的实际含义,那么前期的学习曲线可能会很困难。尽管如此,它比编写任何类型的带锁定的多线程代码要容易得多。
  • 缺点:如果一个计算密集型请求运行了,例如,100 毫秒,它将停止处理在同一个 Node.js 进程中处理的其他请求......又名,协作多任务。这可以通过 Web Workers 模式来缓解(分离出一个子流程来处理昂贵的任务)。或者,您可以使用大量 Node.js 工作人员,并且只让每个工作人员同时处理一个请求(仍然相当有效,因为没有进程回收)。
  • 缺点:运行生产系统比CGI模型(如 Apache + PHP、PerlRuby等)复杂得多。未处理的异常将导致整个过程中断,需要逻辑来重新启动失败的工作程序(请参阅集群)。带有错误本机代码的模块可能会导致进程严重崩溃。每当工作人员死亡时,它正在处理的任何请求都会被丢弃,因此一个有问题的 API 很容易降低其他共同托管 API 的服务。

Versus writing a "real" service in Java / C# / C (C? really?)

与用 Java/C#/C(C?真的?)编写“真正的”服务相比

  • Pro: Doing asynchronous in Node.js is easier than doing thread-safety anywhere else and arguably provides greater benefit. Node.js is by far the least painful asynchronous paradigm I've ever worked in. With good libraries, it is only slightly harder than writing synchronous code.
  • Pro: No multithreading / locking bugs. True, you invest up front in writing more verbose code that expresses a proper asynchronous workflow with no blocking operations. And you need to write some tests and get the thing to work (it is a scripting language and fat fingering variable names is only caught at unit-test time). BUT, once you get it to work, the surface area for heisenbugs-- strange problems that only manifest once in a million runs -- that surface area is just much much lower. The taxes writing Node.js code are heavily front-loaded into the coding phase. Then you tend to end up with stable code.
  • Pro: JavaScript is much more lightweight for expressing functionality. It's hard to prove this with words, but JSON, dynamic typing, lambda notation, prototypal inheritance, lightweight modules, whatever ... it just tends to take less code to express the same ideas.
  • Con: Maybe you really, really like coding services in Java?
  • 优点:在 Node.js 中执行异步比在其他任何地方执行线程安全更容易,并且可以说提供了更大的好处。Node.js 是迄今为止我工作过的最痛苦的异步范式。有了好的库,它只比编写同步代码稍微难一点。
  • 优点:没有多线程/锁定错误。确实,您预先投资编写更详细的代码,以表达没有阻塞操作的正确异步工作流。并且您需要编写一些测试并使其工作(它是一种脚本语言,并且仅在单元测试时捕获到胖指法变量名称)。但是,一旦你让它工作,heisenbugs 的表面积——在一百万次运行中只出现一次的奇怪问题——表面积要低得多。编写 Node.js 代码的税费在编码阶段很重。然后你往往会得到稳定的代码。
  • 优点:JavaScript 在表达功能方面要轻得多。很难用文字来证明这一点,但是JSON、动态类型、lambda 符号、原型继承、轻量级模块等等……它只是倾向于用更少的代码来表达相同的想法。
  • Con:也许你真的非常喜欢 Java 中的编码服务?

For another perspective on JavaScript and Node.js, check out From Java to Node.js, a blog post on a Java developer's impressions and experiences learning Node.js.

有关 JavaScript 和 Node.js 的另一个观点,请查看从 Java 到 Node.js,这是一篇关于 Java 开发人员学习 Node.js 的印象和经验的博客文章。



ModulesWhen considering node, keep in mind that your choice of JavaScript libraries will DEFINEyour experience. Most people use at least two, an asynchronous pattern helper (Step, Futures, Async), and a JavaScript sugar module (Underscore.js).

模块在考虑 node 时,请记住您选择的 JavaScript 库将定义您的体验。大多数人至少使用两个,一个异步模式助手(Step、Futures、Async)和一个 JavaScript 糖模块(Underscore.js)。

Helper / JavaScript Sugar:

助手 / JavaScript 糖:

  • Underscore.js- use this. Just do it. It makes your code nice and readable with stuff like _.isString(), and _.isArray(). I'm not really sure how you could write safe code otherwise. Also, for enhanced command-line-fu, check out my own Underscore-CLI.
  • Underscore.js- 使用这个。去做就对了。它使用 _.isString() 和 _.isArray() 之类的东西使您的代码美观且可读。我不太确定你怎么能写出安全的代码。另外,对于增强的命令行功能,请查看我自己的Underscore-CLI

Asynchronous Pattern Modules:

异步模式模块:

  • Step- a very elegant way to express combinations of serial and parallel actions. My personal reccomendation. See my poston what Step code looks like.
  • Futures- much more flexible (is that really a good thing?) way to express ordering through requirements. Can express things like "start a, b, c in parallel. When A, and B finish, start AB. When A, and C finish, start AC." Such flexibility requires more care to avoid bugs in your workflow (like never calling the callback, or calling it multiple times). See Raynos's poston using futures (this is the post that made me "get" futures).
  • Async- more traditional library with one method for each pattern. I started with this before my religious conversion to step and subsequent realization that all patterns in Async could be expressed in Step with a single more readable paradigm.
  • TameJS- Written by OKCupid, it's a precompiler that adds a new language primative "await" for elegantly writing serial and parallel workflows. The pattern looks amazing, but it does require pre-compilation. I'm still making up my mind on this one.
  • StreamlineJS- competitor to TameJS. I'm leaning toward Tame, but you can make up your own mind.
  • Step- 一种非常优雅的方式来表达串行和并行动作的组合。我个人的推荐。请参阅关于 Step 代码外观的帖子
  • Futures- 更灵活(这真的是一件好事吗?)通过需求表达订购的方式。可以表达诸如“并行启动a、b、c。当A和B完成时,启动AB。当A和C完成时,启动AC”。这种灵活性需要更加小心以避免工作流程中的错误(例如从不调用回调或多次调用)。请参阅Raynos关于使用期货的帖子这是让我“获得”期货的帖子)。
  • 异步- 更传统的库,每种模式都有一种方法。在我对 step 的宗教转变之前,我从这个开始,随后意识到异步中的所有模式都可以用一个更易读的范式在 Step 中表达。
  • TameJS- 由 OKCupid 编写,它是一个预编译器,它添加了一种新的语言原语“await”,用于优雅地编写串行和并行工作流。该模式看起来很棒,但它确实需要预编译。我还在考虑这个问题。
  • StreamlineJS- TameJS 的竞争对手。我倾向于Tame,但你可以自己决定。

Or to read all about the asynchronous libraries, see this panel-interviewwith the authors.

或者要阅读有关异步库的所有信息,请参阅与作者的小组访谈

Web Framework:

网络框架:

  • ExpressGreat Ruby on Rails-esk framework for organizing web sites. It uses JADEas a XML/HTML templating engine, which makes building HTML far less painful, almost elegant even.
  • jQueryWhile not technically a node module, jQuery is quickly becoming a de-facto standard for client-side user interface. jQuery provides CSS-like selectors to 'query' for sets of DOM elements that can then be operated on (set handlers, properties, styles, etc). Along the same vein, Twitter's BootstrapCSS framework, Backbone.jsfor an MVCpattern, and Browserify.jsto stitch all your JavaScript files into a single file. These modules are all becoming de-facto standards so you should at least check them out if you haven't heard of them.
  • 用于组织网站的ExpressGreat Ruby on Rails-esk 框架。它使用JADE作为 XML/HTML 模板引擎,这使得构建 HTML 的痛苦大大减少,甚至近乎优雅。
  • jQuery虽然在技术上不是一个节点模块,但 jQuery 正迅速成为客户端用户界面的事实上的标准。jQuery 提供类似 CSS 的选择器来“查询”然后可以操作的 DOM 元素集(集处理程序、属性、样式等)。同样,Twitter 的BootstrapCSS 框架、用于MVC模式的Backbone.js用于将所有 JavaScript 文件拼接成单个文件的Browserify.js。这些模块都已成为事实上的标准,因此如果您还没有听说过它们,至少应该检查一下。

Testing:

测试:

  • JSHint- Must use; I didn't use this at first which now seems incomprehensible. JSLint adds back a bunch of the basic verifications you get with a compiled language like Java. Mismatched parenthesis, undeclared variables, typeos of many shapes and sizes. You can also turn on various forms of what I call "anal mode" where you verify style of whitespace and whatnot, which is OK if that's your cup of tea -- but the real value comes from getting instant feedback on the exact line number where you forgot a closing ")" ... without having to run your code and hit the offending line. "JSHint" is a more-configurable variant of Douglas Crockford's JSLint.
  • Mochacompetitor to Vows which I'm starting to prefer. Both frameworks handle the basics well enough, but complex patterns tend to be easier to express in Mocha.
  • VowsVows is really quite elegant. And it prints out a lovely report (--spec) showing you which test cases passed / failed. Spend 30 minutes learning it, and you can create basic tests for your modules with minimal effort.
  • Zombie- Headless testing for HTML and JavaScript using JSDomas a virtual "browser". Very powerful stuff. Combine it with Replayto get lightning fast deterministic tests of in-browser code.
  • A comment on how to "think about" testing:
    • Testing is non-optional. With a dynamic language like JavaScript, there are veryfew static checks. For example, passing two parameters to a method that expects 4 won't break until the code is executed. Pretty low bar for creating bugs in JavaScript. Basic tests are essential to making up the verification gap with compiled languages.
    • Forget validation, just make your code execute. For every method, my first validation case is "nothing breaks", and that's the case that fires most often. Proving that your code runs without throwing catches 80% of the bugs and will do so much to improve your code confidence that you'll find yourself going back and adding the nuanced validation cases you skipped.
    • Start small and break the inertial barrier. We are all lazy, and pressed for time, and it's easy to see testing as "extra work". So start small. Write test case 0 - load your module and report success. If you force yourself to do just this much, then the inertial barrier to testing is broken. That's <30 min to do it your first time, including reading the documentation. Now write test case 1 - call one of your methods and verify "nothing breaks", that is, that you don't get an error back. Test case 1 should take you less than one minute. With the inertia gone, it becomes easy to incrementally expand your test coverage.
    • Now evolve your tests with your code. Don't get intimidated by what the "correct" end-to-end test would look like with mock servers and all that. Code starts simple and evolves to handle new cases; tests should too. As you add new cases and new complexity to your code, add test cases to exercise the new code. As you find bugs, add verifications and / or new cases to cover the flawed code. When you are debugging and lose confidence in a piece of code, go back and add tests to prove that it is doing what you think it is. Capture strings of example data (from other services you call, websites you scrape, whatever) and feed them to your parsing code. A few cases here, improved validation there, and you will end up with highly reliable code.
  • JSHint- 必须使用;一开始我没有使用这个,现在似乎无法理解。JSLint 添加了您使用 Java 等编译语言获得的一系列基本验证。不匹配的括号、未声明的变量、多种形状和大小的类型。您还可以打开我称之为“肛门模式”的各种形式,您可以在其中验证空格和诸如此类的样式,如果这是您的一杯茶,那就可以了——但真正的价值来自于获得关于确切行号的即时反馈,其中你忘记了一个结束的“)”......而不必运行你的代码并点击违规行。“JSHint”是Douglas CrockfordJSLint 的一个更可配置的变体。
  • Mocha是 Vows 的竞争对手,我开始喜欢它。这两个框架都可以很好地处理基础知识,但复杂的模式在 Mocha 中更容易表达。
  • VowsVows 真的很优雅。它会打印出一个可爱的报告 (--spec),显示哪些测试用例通过/失败。花 30 分钟学习它,您就可以轻松地为您的模块创建基本测试。
  • Zombie- 使用JSDom作为虚拟“浏览器”对 HTML 和 JavaScript 进行无头测试。很强大的东西。将其与Replay结合使用,可以对浏览器内代码进行闪电般的快速确定性测试。
  • 关于如何“思考”测试的评论:
    • 测试是非可选的。有了这样的JavaScript动态语言,也有少数的静态检查。例如,将两个参数传递给期望 4 的方法在代码执行之前不会中断。在 JavaScript 中创建错误的门槛很低。基本测试对于弥补与编译语言的验证差距至关重要。
    • 忘记验证,只需执行您的代码。对于每种方法,我的第一个验证案例都是“没有任何问题”,这是最常触发的情况。证明您的代码在不抛出的情况下运行可以捕获 80% 的错误,并且可以极大地提高您的代码信心,您会发现自己回去并添加您跳过的细微验证案例。
    • 从小处着手,打破惯性障碍。我们都很懒惰,时间紧迫,很容易将测试视为“额外工作”。所以从小事做起。编写测试用例 0 - 加载您的模块并报告成功。如果你强迫自己做这么多,那么测试的惯性障碍就会​​被打破。第一次做这件事不到 30 分钟,包括阅读文档。现在编写测试用例 1 - 调用您的方法之一并验证“没有任何问题”,也就是说,您没有收到错误消息。测试用例 1 应该花不到一分钟的时间。随着惯性的消失,逐步扩展您的测试覆盖范围变得很容易。
    • 现在用您的代码改进您的测试。不要被模拟服务器和所有这些的“正确”端到端测试的样子吓倒。代码从简单开始,然后演变以处理新情况;测试也应该。当您向代码添加新案例和新复杂性时,请添加测试案例来练习新代码。当您发现错误时,添加验证和/或新案例以覆盖有缺陷的代码。当您正在调试并且对一段代码失去信心时,请返回并添加测试以证明它正在执行您认为的操作。捕获示例数据字符串(来自您调用的其他服务、您抓取的网站等)并将它们提供给您的解析代码。这里有几个案例,那里改进了验证,你最终会得到高度可靠的代码。

Also, check out the official listof recommended Node.js modules. However, GitHub'sNode Modules Wikiis much more complete and a good resource.

另外,请查看推荐的 Node.js 模块的官方列表。但是,GitHub 的Node Modules Wiki更加完整,并且是一个很好的资源。



To understand Node, it's helpful to consider a few of the key design choices:

要理解 Node,考虑一些关键的设计选择会很有帮助:

Node.js is EVENT BASEDand ASYNCHRONOUS/ NON-BLOCKING. Events, like an incoming HTTP connection will fire off a JavaScript function that does a little bit of work and kicks off other asynchronous tasks like connecting to a database or pulling content from another server. Once these tasks have been kicked off, the event function finishes and Node.js goes back to sleep. As soon as something else happens, like the database connection being established or the external server responding with content, the callback functions fire, and more JavaScript code executes, potentially kicking off even more asynchronous tasks (like a database query). In this way, Node.js will happily interleave activities for multiple parallel workflows, running whatever activities are unblocked at any point in time. This is why Node.js does such a great job managing thousands of simultaneous connections.

Node.js基于事件异步/非阻塞. 事件(如传入的 HTTP 连接)将触发 JavaScript 函数,该函数执行一些工作并启动其他异步任务,如连接到数据库或从另一台服务器提取内容。一旦这些任务被启动,事件函数就会结束,Node.js 会重新进入睡眠状态。一旦发生其他事情,比如建立数据库连接或外部服务器响应内容,回调函数就会触发,更多的 JavaScript 代码执行,可能会启动更多的异步任务(比如数据库查询)。通过这种方式,Node.js 将愉快地为多个并行工作流交错活动,在任何时间点运行任何不受阻止的活动。这就是 Node.js 在管理数千个并发连接方面做得如此出色的原因。

Why not just use one process/thread per connection like everyone else?In Node.js, a new connection is just a very small heap allocation. Spinning up a new process takes significantly more memory, a megabyte on some platforms. But the real cost is the overhead associated with context-switching. When you have 10^6 kernel threads, the kernel has to do a lot of work figuring out who should execute next. A bunch of work has gone into building an O(1) scheduler for Linux, but in the end, it's just way way more efficient to have a single event-driven process than 10^6 processes competing for CPU time. Also, under overload conditions, the multi-process model behaves very poorly, starving critical administration and management services, especially SSHD (meaning you can't even log into the box to figure out how screwed it really is).

为什么不像其他人一样为每个连接使用一个进程/线程?在 Node.js 中,一个新的连接只是一个非常小的堆分配。启动一个新进程需要更多的内存,在某些平台上为 MB。但真正的成本是与上下文切换相关的开销。当您有 10^6 个内核线程时,内核必须做很多工作来确定下一个应该执行谁。为 Linux 构建 O(1) 调度程序已经进行了大量工作,但最终,与竞争 CPU 时间的 10^6 个进程相比,拥有单个事件驱动进程的效率更高。此外,在过载条件下,多进程模型的表现非常糟糕,关键的管理和管理服务匮乏,尤其是 SSHD(这意味着您甚至无法登录盒子以了解它到底有多糟糕)。

Node.js is SINGLE THREADEDand LOCK FREE. Node.js, as a very deliberate design choice only has a single thread per process. Because of this, it's fundamentally impossible for multiple threads to access data simultaneously. Thus, no locks are needed. Threads are hard. Really really hard. If you don't believe that, you haven't done enough threaded programming. Getting locking right is hard and results in bugs that are really hard to track down. Eliminating locks and multi-threading makes one of the nastiest classes of bugs just go away. This might be the single biggest advantage of node.

Node.js 是单线程和无锁的。Node.js,作为一个非常深思熟虑的设计选择,每个进程只有一个线程。因此,多个线程同时访问数据从根本上是不可能的。因此,不需要锁。线程很难。真的真的很难。如果您不相信这一点,那么您还没有完成足够的线程编程。正确锁定很难,并且会导致很难追踪的错误。消除锁和多线程使最严重的错误类别之一消失了。这可能是 node.js 的最大优势。

But how do I take advantage of my 16 core box?

但是我如何利用我的 16 核盒子呢?

Two ways:

两种方式:

  1. For big heavy compute tasks like image encoding, Node.js can fire up child processes or send messages to additional worker processes. In this design, you'd have one thread managing the flow of events and N processes doing heavy compute tasks and chewing up the other 15 CPUs.
  2. For scaling throughput on a webservice, you should run multiple Node.js servers on one box, one per core, using cluster(With Node.js v0.6.x, the official "cluster" module linked here replaces the learnboost version which has a different API). These local Node.js servers can then compete on a socket to accept new connections, balancing load across them. Once a connection is accepted, it becomes tightly bound to a single one of these shared processes. In theory, this sounds bad, but in practice it works quite well and allows you to avoid the headache of writing thread-safe code. Also, this means that Node.js gets excellent CPU cache affinity, more effectively using memory bandwidth.
  1. 对于像图像编码这样的大型繁重计算任务,Node.js 可以启动子进程或向其他工作进程发送消息。在此设计中,您将有一个线程来管理事件流和 N 个进程执行繁重的计算任务并占用其他 15 个 CPU。
  2. 为了扩展 Web 服务的吞吐量,您应该在一个机器上运行多个 Node.js 服务器,每个核心一个,使用集群(使用 Node.js v0.6.x,此处链接的官方“集群”模块取代了具有不同的 API)。然后,这些本地 Node.js 服务器可以在套接字上竞争以接受新连接,从而平衡它们之间的负载。一旦连接被接受,它就会与这些共享进程中的一个紧密绑定。理论上,这听起来很糟糕,但在实践中它工作得很好,并且可以让您避免编写线程安全代码的麻烦。此外,这意味着 Node.js 获得了出色的 CPU 缓存亲和力,可以更有效地使用内存带宽。

Node.js lets you do some really powerful things without breaking a sweat.Suppose you have a Node.js program that does a variety of tasks, listens on a TCPport for commands, encodes some images, whatever. With five lines of code, you can add in an HTTP based web management portal that shows the current status of active tasks. This is EASY to do:

Node.js 让你可以毫不费力地做一些非常强大的事情。假设您有一个 Node.js 程序,它执行各种任务、侦听TCP端口的命令、编码一些图像等等。使用五行代码,您可以添加一个基于 HTTP 的 Web 管理门户,显示活动任务的当前状态。这很容易做到:

var http = require('http');
http.createServer(function (req, res) {
    res.writeHead(200, {'Content-Type': 'text/plain'});
    res.end(myJavascriptObject.getSomeStatusInfo());
}).listen(1337, "127.0.0.1");

Now you can hit a URL and check the status of your running process. Add a few buttons, and you have a "management portal". If you have a running Perl / Python / Ruby script, just "throwing in a management portal" isn't exactly simple.

现在您可以点击一个 URL 并检查您正在运行的进程的状态。添加几个按钮,您就有了一个“管理门户”。如果您有一个正在运行的 Perl/Python/Ruby 脚本,那么仅仅“加入管理门户”并不简单。

But isn't JavaScript slow / bad / evil / spawn-of-the-devil?JavaScript has some weird oddities, but with "the good parts" there's a very powerful language there, and in any case, JavaScript is THE language on the client (browser). JavaScript is here to stay; other languages are targeting it as an IL, and world class talent is competing to produce the most advanced JavaScript engines. Because of JavaScript's role in the browser, an enormous amount of engineering effort is being thrown at making JavaScript blazing fast. V8is the latest and greatest javascript engine, at least for this month. It blows away the other scripting languages in both efficiency AND stability (looking at you, Ruby). And it's only going to get better with huge teams working on the problem at Microsoft, Google, and Mozilla, competing to build the best JavaScript engine (It's no longer a JavaScript "interpreter" as all the modern engines do tons of JITcompiling under the hood with interpretation only as a fallback for execute-once code). Yeah, we all wish we could fix a few of the odder JavaScript language choices, but it's really not that bad. And the language is so darn flexible that you really aren't coding JavaScript, you are coding Step or jQuery -- more than any other language, in JavaScript, the libraries define the experience. To build web applications, you pretty much have to know JavaScript anyway, so coding with it on the server has a sort of skill-set synergy. It has made me not dread writing client code.

但是 JavaScript 是不是很慢/不好/邪恶/恶魔之子?JavaScript 有一些奇怪的奇怪之处,但在“好的部分”中有一种非常强大的语言,无论如何,JavaScript 是客户端(浏览器)上的语言。JavaScript 将继续存在;其他语言将其作为 IL 目标,世界一流的人才正在竞相生产最先进的 JavaScript 引擎。由于 JavaScript 在浏览器中的作用,大量的工程工作被投入到让 JavaScript 快速运行中。 V8是最新最好的 javascript 引擎,至少在这个月是这样。它在效率和稳定性方面击败了其他脚本语言(看着你,Ruby)。它只会随着微软、谷歌和 Mozilla 的庞大团队在这个问题上的工作而变得更好,竞争构建最好的 JavaScript 引擎(它不再是一个 JavaScript“解释器”,因为所有现代引擎都做了大量的JIT在引擎盖下编译并解释仅作为执行一次代码的后备)。是的,我们都希望我们可以修复一些奇怪的 JavaScript 语言选择,但这真的没那么糟糕。而且该语言非常灵活,您实际上不是在编写 JavaScript,而是在编写 Step 或 jQuery —— 比任何其他语言都多,在 JavaScript 中,库定义了体验。无论如何,要构建 Web 应用程序,您几乎都必须了解 JavaScript,因此在服务器上使用它进行编码具有某种技能集协同作用。它让我不再害怕编写客户端代码。

Besides, if you REALLY hate JavaScript, you can use syntactic sugar like CoffeeScript. Or anything else that creates JavaScript code, like Google Web Toolkit(GWT).

此外,如果你真的讨厌 JavaScript,你可以使用像CoffeeScript这样的语法糖。或者任何其他创建 JavaScript 代码的东西,比如Google Web Toolkit(GWT)。

Speaking of JavaScript, what's a "closure"?- Pretty much a fancy way of saying that you retain lexically scoped variables across call chains. ;) Like this:

说到 JavaScript,什么是“闭包”?- 几乎是一种奇特的说法,即跨调用链保留词法作用域的变量。;) 像这样:

var myData = "foo";
database.connect( 'user:pass', function myCallback( result ) {
    database.query("SELECT * from Foo where id = " + myData);
} );
// Note that doSomethingElse() executes _BEFORE_ "database.query" which is inside a callback
doSomethingElse();

See how you can just use "myData" without doing anything awkward like stashing it into an object? And unlike in Java, the "myData" variable doesn't have to be read-only. This powerful language feature makes asynchronous-programming much less verbose and less painful.

看看你如何只使用“myData”而不用做任何尴尬的事情,比如把它藏在一个对象中?与 Java 不同的是,“myData”变量不必是只读的。这种强大的语言特性使异步编程变得不那么冗长和痛苦。

Writing asynchronous code is always going to be more complex than writing a simple single-threaded script, but with Node.js, it's not that much harder and you get a lot of benefits in addition to the efficiency and scalability to thousands of concurrent connections...

编写异步代码总是比编写一个简单的单线程脚本更复杂,但是使用 Node.js,它并没有那么难,除了效率和可扩展到数千个并发连接之外,您还可以获得很多好处。 ..

回答by rfunduk

V8is an implementation of JavaScript. It lets you run standalone JavaScript applications (among other things).

V8是 JavaScript 的一个实现。它允许您运行独立的 JavaScript 应用程序(除其他外)。

Node.js is simply a library written for V8 which does evented I/O. This concept is a bit trickier to explain, and I'm sure someone will answer with a better explanation than I... The gist is that rather than doing some input or output and waiting for it to happen, you just don'twait for it to finish. So for example, ask for the last edited time of a file:

Node.js 只是一个为 V8 编写的库,它执行事件 I/O。这个概念解释起来有点棘手,我相信有人会用比我更好的解释来回答......要点是,与其做一些输入或输出并等待它发生,你只是不要等待让它完成。例如,询问文件的上次编辑时间:

// Pseudo code
stat( 'somefile' )

That might take a couple of milliseconds, or it might take seconds. With evented I/Oyou simply fire off the request and instead of waiting around you attach a callback that gets run when the request finishes:

这可能需要几毫秒,也可能需要几秒钟。使用事件I/O,您只需触发请求,而不是等待您附加一个在请求完成时运行的回调:

// Pseudo code
stat( 'somefile', function( result ) {
  // Use the result here
} );
// ...more code here

This makes it a lot like JavaScript code in the browser (for example, with Ajaxstyle functionality).

这使它很像浏览器中的 JavaScript 代码(例如,具有Ajax样式功能)。

For more information, you should check out the article Node.js is genuinely excitingwhich was my introduction to the library/platform... I found it quite good.

有关更多信息,您应该查看文章Node.js 真的令人兴奋,这是我对库/平台的介绍......我发现它非常好。

回答by Asif Mushtaq

Node.jsis an open source command line tool built for the server side JavaScript code. You can download a tarball, compile and install the source. It lets you run JavaScript programs.

Node.js是为服务器端 JavaScript 代码构建的开源命令行工具。您可以下载tarball,编译并安装源代码。它允许您运行 JavaScript 程序。

The JavaScript is executed by the V8, a JavaScript engine developed by Google which is used in Chromebrowser. It uses a JavaScript API to access the network and file system.

JavaScript 由V8执行,V8是谷歌开发的 JavaScript 引擎,用于Chrome浏览器。它使用 JavaScript API 来访问网络和文件系统。

It is popular for its performance and the ability to perform parallel operations.

它因其性能和执行并行操作的能力而广受欢迎。

Understanding node.jsis the best explanation of node.jsI have found so far.

理解 node.js是迄今为止我发现的对node.js最好的解释。

Following are some good articles on the topic.

以下是一些关于该主题的好文章。

回答by Fire Crow

The closures are a way to execute code in the context it was created in.

闭包是在创建代码的上下文中执行代码的一种方式。

What this means for concurency is that you can define variables, then initiate a nonblocking I/Ofunction, and send it an anonymous function for its callback.

这对于并发性意味着您可以定义变量,然后启动一个非阻塞I/O函数,并为其回调发送一个匿名函数。

When the task is complete, the callback function will execute in the context with the variables, this is the closure.

当任务完成时,回调函数将在带有变量的上下文中执行,这就是闭包。

The reason closures are so good for writing applications with nonblocking I/O is that it's very easy to manage the context of functions executing asynchronously.

闭包非常适合编写具有非阻塞 I/O 的应用程序的原因是,管理异步执行的函数的上下文非常容易。

回答by Renato

Two good examples are regarding how you manage templates and use progressive enhancements with it. You just need a few lightweight pieces of JavaScript code to make it work perfectly.

两个很好的例子是关于如何管理模板和使用它的渐进增强。您只需要一些轻量级的 JavaScript 代码即可使其完美运行。

I strongly recommend that you watch and read these articles:

我强烈建议您观看并阅读以下文章:

Pick up any language and try to remember how you would manage your HTML file templates and what you had to do to update a single CSSclass name in your DOMstructure (for instance, a user clicked on a menu item and you want that marked as "selected" and update the content of the page).

选择任何一种语言并尝试记住您将如何管理您的 HTML 文件模板以及您必须做什么才能更新DOM结构中的单个CSS类名称(例如,用户单击了一个菜单项,并且您希望将其标记为“选中”并更新页面内容)。

With Node.js it is as simple as doing it in client-side JavaScript code. Get your DOM node and apply your CSS class to that. Get your DOM node and innerHTML your content (you will need some additional JavaScript code to do this. Read the article to know more).

使用 Node.js 就像在客户端 JavaScript 代码中一样简单。获取您的 DOM 节点并将您的 CSS 类应用于该节点。获取您的 DOM 节点和 innerHTML 您的内容(您将需要一些额外的 JavaScript 代码来执行此操作。阅读文章以了解更多信息)。

Another good example, is that you can make your web page compatible both with JavaScript turned on or off with the same piece of code. Imagine you have a date selection made in JavaScript that would allow your users to pick up any date using a calendar. You can write (or use) the same piece of JavaScript code to make it work with your JavaScript turned ON or OFF.

另一个很好的例子是,您可以使用同一段代码使您的网页与打开或关闭的 JavaScript 兼容。假设您有一个用 JavaScript 选择的日期,它允许您的用户使用日历选择任何日期。您可以编写(或使用)同一段 JavaScript 代码,使其在打开或关闭 JavaScript 的情况下工作。

回答by adeleinr

There is a very good fast food place analogy that best explains the event driven model of Node.js, see the full article, Node.js, Doctor's Offices and Fast Food Restaurants – Understanding Event-driven Programming

有一个非常好的快餐店比喻,最能解释 Node.js 的事件驱动模型,请参阅完整文章Node.js,Doctor's Offices 和 Fast Food Restaurants – Understanding Event-driven Programming

Here is a summary:

这是一个总结:

If the fast food joint followed a traditional thread-based model, you'd order your food and wait in line until you received it. The person behind you wouldn't be able to order until your order was done. In an event-driven model, you order your food and then get out of line to wait. Everyone else is then free to order.

如果快餐店遵循传统的基于线程的模式,您将订购食物并排队等待直到您收到食物。在您的订单完成之前,您身后的人将无法订购。在事件驱动模型中,您订购食物,然后排队等候。然后其他所有人都可以自由订购。

Node.js is event-driven, but most web servers are thread-based.York explains how Node.js works:

Node.js 是事件驱动的,但大多数 Web 服务器都是基于线程的。York 解释了 Node.js 的工作原理:

  • You use your web browser to make a request for "/about.html" on a Node.js web server.

  • The Node.js server accepts your request and calls a function to retrieve that file from disk.

  • While the Node.js server is waiting for the file to be retrieved, it services the next web request.

  • When the file is retrieved, there is a callback function that is inserted in the Node.js servers queue.

  • The Node.js server executes that function which in this case would render the "/about.html" page and send it back to your web browser."

  • 您使用 Web 浏览器在 Node.js Web 服务器上请求“/about.html”。

  • Node.js 服务器接受您的请求并调用一个函数来从磁盘检索该文件。

  • 当 Node.js 服务器正在等待检索文件时,它会为下一个 Web 请求提供服务。

  • 检索文件时,会在 Node.js 服务器队列中插入一个回调函数。

  • Node.js 服务器执行该函数,在这种情况下,它将呈现“/about.html”页面并将其发送回您的 Web 浏览器。”

回答by Quinton Pike

Also, do not forget to mention that Google's V8 is VERY fast. It actually converts the JavaScript code to machine code with the matched performance of compiled binary. So along with all the other great things, it's INSANELY fast.

另外,不要忘记提到 Google 的 V8 非常快。它实际上将 JavaScript 代码转换为机器代码,并具有与编译后的二进制文件相匹配的性能。因此,连同所有其他伟大的事情,它的速度非常快。

回答by nes1983

Well, I understand that

嗯,我明白了

  • Node's goal is to provide an easy way to build scalable network programs.
  • Node is similar in design to and influenced by systems like Ruby's Event Machine or Python's Twisted.
  • Evented I/O for V8 javascript.
  • Node 的目标是提供一种简单的方法来构建可扩展的网络程序。
  • Node 在设计上类似于 Ruby 的 Event Machine 或 Python 的 Twisted 等系统,并受其影响。
  • V8 javascript 的事件 I/O。

For me that means that you were correct in all three assumptions. The library sure looks promising!

对我来说,这意味着您在所有三个假设中都是正确的。图书馆肯定看起来很有前途!

回答by Charles

Q: The programming model is event driven, especially the way it handles I/O.

问:编程模型是事件驱动的,尤其是它处理I/O 的方式

Correct. It uses call-backs, so any request to access the file system would cause a request to be sent to the file system and then Node.js would start processing its next request. It would only worry about the I/O request once it gets a response back from the file system, at which time it will run the callback code. However, it is possible to make synchronous I/O requests (that is, blocking requests). It is up to the developer to choose between asynchronous (callbacks) or synchronous (waiting).

正确的。它使用回调,因此任何访问文件系统的请求都会导致一个请求被发送到文件系统,然后 Node.js 将开始处理它的下一个请求。一旦它从文件系统得到响应,它就会只关心 I/O 请求,此时它会运行回调代码。但是,可以进行同步 I/O 请求(即阻塞请求)。由开发人员在异步(回调)或同步(等待)之间进行选择。

Q: It uses JavaScript and the parser is V8.

Q:它使用JavaScript,解析器是V8。

Yes

是的

Q: It can be easily used to create concurrent server applications.

问:它可以很容易地用于创建并发服务器应用程序。

Yes, although you'd need to hand-code quite a lot of JavaScript. It might be better to look at a framework, such as http://www.easynodejs.com/- which comes with full online documentation and a sample application.

是的,尽管您需要手动编写大量 JavaScript。最好查看一个框架,例如http://www.easynodejs.com/- 它带有完整的在线文档和示例应用程序。