TE
科技回声
首页24小时热榜最新最佳问答展示工作
GitHubTwitter
首页

科技回声

基于 Next.js 构建的科技新闻平台,提供全球科技新闻和讨论内容。

GitHubTwitter

首页

首页最新最佳问答展示工作

资源链接

HackerNews API原版 HackerNewsNext.js

© 2025 科技回声. 版权所有。

An open question (rant) about Node.js

93 点作者 jobeirne大约 11 年前

28 条评论

ef4大约 11 年前
It&#x27;s worse than that: it&#x27;s true that in-process asynchronicity is a performance optimization, but it doesn&#x27;t follow at all that the code needs to <i>read</i> asynchronously.<p>There is no performance reason to make developers hand-code in the continuation-passing style. That should be the job of a compiler or runtime environment.<p>Erlang does it. Stackless Python does it. Go does it.<p>The whole &quot;look how fast Node is due to all my hand-rolled callbacks&quot; is a total fallacy. It&#x27;s a case of taking perverse pride in an accidental wart of your language.<p>Slowly the node community is maturing and beginning to realize that if they want to build robust, fault-tolerant software they need better primitives than hand-rolled callbacks. Hence the slowly rising mindshare of Promises, which are strictly better, but would be better still if the language itself baked them in implicitly (consider that nearly any value in a Haskell program is represented by a promise under the hood, but you never have to deal with them explicitly).
评论 #7399283 未加载
评论 #7399510 未加载
评论 #7399980 未加载
评论 #7399438 未加载
评论 #7399670 未加载
评论 #7399463 未加载
erjiang大约 11 年前
<i>Please stop asking questions like this about Node.js.</i><p>The superfluous obtuse complexity that node.js forces is what&#x27;s keeping ninja programmers like us employed. If we don&#x27;t keep switching to strange new things every few years, our wages will stagnate as there&#x27;s less separating our rock-star tech from lower-salaried uncool &quot;enterprise&quot; software.<p>Being able to manually manage continuations rather than using a language that does it for us is a high barrier that keeps us in demand, the same way that having to manage memory manually keeps people from becoming C programmers. Losing this edge is not something we should encourage.<p>Just imagine - if all of these &quot;learn to code&quot; programs actually work, the market will be flooded with new programmers. Thankfully, if we make sure that they only learn easy things like Python, we can continue to convince the world that things like Node.js and MongoDB are the future. While the rest of the world is still catching up on basics like Python and Postgres, we&#x27;ll be one step ahead of them.<p>People questioning Node.js like this more and more are a sign that we need to find the next hotness and move there if&#x2F;when node.js sinks. If we can convince people to build more things in the next hotness, then we can get in early before the masses pick up on it, ensuring that we can maintain our spendy lifestyles and free lunches in SF.<p>(&#x2F;s)
评论 #7401839 未加载
bitwize大约 11 年前
Here&#x27;s a fun fact that every Amiga programmer seems to understand that Unix programmers just never really got: actual computing hardware is <i>inherently</i> asynchronous and interrupt-driven. The whole Amiga system is structured around using the CPU to program the custom chips and initiate DMA transfers, and installing interrupt handlers that perform the next phase of the program once the custom chips finished their work. It&#x27;s <i>how shit got done</i> on the Amiga. By contrast, the lack of good support in early Unix for asynchronous I&#x2F;O is said to be one of the reasons why X11 is such an ugly pile of hacks.<p>Even on Unix, if you wrote a server procedurally what you&#x27;d end up doing is having main() start a select loop that... dispatches incoming events to callbacks. All Node does really is to abstract away the select loop -- one less thing for the developer to worry about. The Node way is <i>simpler</i> than the conventional C way.<p>So no, there&#x27;s nothing inherently superior about linear, procedural code, especially when such code is not at all how a computer system that must interact with the outside world works. Whether asynchronous, callback-driven code is confusing or not depends on what background you come from. Put an old-school scener in front of Node and he might form an entirely different opinion about it from OP.
评论 #7401310 未加载
robgering大约 11 年前
I understand that Node.js is really popular here and that my opinion may be an unpopular one. Maybe this will change, but I cannot find a use case for Node where I wouldn&#x27;t choose something else.<p>If I want to prototype (performance is not a constraint), I&#x27;d use Ruby (or Python) before Node. If I need concurrency or if performance is a constraint, I&#x27;d choose Go (or Clojure, or Scala, or Erlang) before Node. I understand the argument about using JavaScript throughout the stack, but I see this as specious at best. Front-end and back-end development require different domain knowledge, not just language proficiency.<p>Perhaps using Node opens a project to a larger community of developers. But under this argument, using C or Java also seems a good choice.
评论 #7399286 未加载
评论 #7399427 未加载
评论 #7399959 未加载
dap大约 11 年前
There&#x27;s no sane possibility of a hybrid for Node.js. The concurrency model in JavaScript is built for one thread [that runs JavaScript]. For servers, in such a model, <i>everything</i> has to be async. A 20ms synchronous operation means 20ms of time that you cannot handle new connections or process others that have sent or received data. It&#x27;s critical to the success of the platform that almost everyone insist on async-only code. Recall that the asynchronous model has been done before by Twisted and EventMachine, but they have exactly this problem: there&#x27;s tons of Python and Ruby code out there that&#x27;s synchronous and if you accidentally use it (even by using a dependency of a dependency), the server falls over. In Node, it&#x27;s very hard to accidentally use it, by design: you have to write an add-on or use one of the few *Sync functions, which are well-known as red flags in a server.<p>In terms of why this model is compelling: it scales well, and it&#x27;s a relatively simple model of synchronization. The 5-line HTTP server on nodejs.org scales to a very large number of requests per second. Having spent a lot of time in the heavily multi-threaded C world (and loving it, btw), it&#x27;s much harder to shoot yourself in the foot with JS and this model, and the failure modes are usually less severe. (Many C programs use this model as well, including haproxy and much of the kernel.)<p>It&#x27;s not all win. Blocked operations are harder to debug. But you can work around things like that, and overall it&#x27;s a nice environment. And FWIW, once you&#x27;re familiar with it, the waterfall pattern quickly becomes as second-nature as writing synchronous code. (More complex ones are still tricky, but the basics do become second-nature.)<p>[edit: I meant that there&#x27;s no sane possibility of a hybrid between synchronous and asynchronous semantics. That doesn&#x27;t mean you couldn&#x27;t use a language feature to make async code look synchronous. That&#x27;s a much more subjective discussion, but I prefer explicitness over compiler magic.]
评论 #7399226 未加载
pessimizer大约 11 年前
I can&#x27;t speak to node (don&#x27;t use it), but in Erlang, I find async far easier to reason about than sync for the simple reason that I don&#x27;t have to plan for what will happen if some operation over the network breaks <i>during</i> a request.<p>In my head, there&#x27;s no difference between async and sync. A synchronous call is just an async message + and async acknowledgement of receipt. If I write it that way, there&#x27;s a lot of failure modes that I don&#x27;t have to think about.<p>Also, in my head, concurrent code looks like a sparse group of people spread over a large, grassy, hilly plot of land shouting at each other from differing heights and many yards distance over the whine of shifting winds. I find it easier to reason about the shouts alone, instead of shouts + their responses, because a response is nothing but another shout.
bitcrusher大约 11 年前
I have a hard time &#x27;listening&#x27; to these rants about how hard it is to reason about asynchronous code. It&#x27;s NOT hard, it&#x27;s DIFFERENT.<p>This isn&#x27;t some new Node-Sauce. The idea of an event-loop asychronous programming domain has been around forever in various forms, first in games and desktop GUI programming and the way one reasons about it hasn&#x27;t changed, just because it has been applied to a new class of problems.<p>I suspect that there are two things going on here:<p>1. A LOT of people dislike Javascript. As a result, they&#x27;re starting with that negative point of view and then finding reasons to support it.<p>This is not unlike people who argue about Python white-space. They&#x27;re really saying &quot;I don&#x27;t like Python.&quot; The white-space issue is incidental.<p>2. Lack of experience &#x2F; exposure<p>I suspect that folks who have trouble with this, frankly just aren&#x27;t experienced enough. I&#x27;m not saying they aren&#x27;t skilled, just not experienced in this realm.<p>Once upon a time, these same sorts of &#x27;arguments&#x27; were used against Ruby ( ala the Rails explosion ). Nothing much has changed about Ruby, other than it has managed to be around long enough to influence a new generation of programmers.
评论 #7400089 未加载
评论 #7400271 未加载
sync大约 11 年前
Async code is super easy to reason about when using ES6 Generators, which are available now in node v0.11.<p>Here&#x27;s both a series and a waterfall example: <a href="https://github.com/visionmedia/co#example" rel="nofollow">https:&#x2F;&#x2F;github.com&#x2F;visionmedia&#x2F;co#example</a>
woola大约 11 年前
Having written nodejs for about an year I would never choose it again if I have given the choice.<p>* No Error handling. The process has to be restarted if something goes wrong.<p>* No thread local storage equivalent. As a result you can&#x27;t do simple thing like differentiate log originated from different http requests.<p>* Callback makes the code unreadable<p>* Javascript has no real method or in other words &#x27;this&#x27; is not attached to a function and is determined by way the function is called. So you have to wrap most of the callbacks with _.bind()<p>* Mixing callback, promise and event emitter api introduce lot of boilerplate code.<p>* No stacktrace. Debugging error is PITA<p>* No preemptive scheduling. So you have to be extra careful that you never spend too much CPU time.<p>* No easy way to handle back pressure.
评论 #7400360 未加载
christiansmith大约 11 年前
The gist reads like someone looking for an excuse to give up and move on. Every time I run across someone bitching about Node&#x27;s programming model I&#x27;m reminded of &quot;The Blub Paradox&quot;.<p><a href="http://paulgraham.com/avg.html" rel="nofollow">http:&#x2F;&#x2F;paulgraham.com&#x2F;avg.html</a><p>I have to admit that learning to think in callbacks was <i>initially</i> an exercise in frustration. But it wasn&#x27;t <i>that</i> hard.<p>Most of the pyramid-type issues can be resolved by applying principles that are also valid in synchronous environments (like modularity).<p>If modules and named functions aren&#x27;t enough, you can subclass EventEmitter to further decouple. For more complex cases there&#x27;s <a href="https://github.com/caolan/async" rel="nofollow">https:&#x2F;&#x2F;github.com&#x2F;caolan&#x2F;async</a>, which makes many nontrivial async problems relatively easy.<p>Why is it so hard for so many people to appreciate Node for its merits? The code isn&#x27;t going to execute in a perfectly linear way, so why should it have to be written as if it were?
pkinsky大约 11 年前
Asynchronicity is great, but javascript doesn&#x27;t provide the tools to do it properly.<p>&gt; (...) try writing a function call that requires information from two separate HTTP API responses; I basically need to draw a diagram of what happens with async.waterfall for a task that, given synchronicity, would&#x27;ve been solved with a trivial three-liner.<p>It&#x27;s a lot easier to handle asynchronicity in strongly-typed languages with monadic for comprehensions. In Scala, for example:<p><pre><code> val res: Future[Foobar] = for { a &lt;- makeHttpRequestA() b &lt;- makeHttpRequestBFromA(a) } yield new Foobar(a, b) </code></pre> You can then register callback functions which operate on either a Success[Foobar] or a Failure[Throwable].<p>Synchronous code isn&#x27;t simpler, it just hides complexity like caltrops in tall grass.<p>(slightly modified version of my post on Github)
评论 #7399808 未加载
neya大约 11 年前
I was reading somewhere (maybe Hackernews itself?) that synchronous programming and&#x2F;or blocking are actually features and not disadvantages. After working on a huge Node.JS project, I regret taking on anyway (I had to do it for the moolah, aka money). I am now convinced that migrating from Rails to Express (A node.Js framework) was a total mistake. Please note, I do not mean to advertise rails in particular, infact, you can replace rails with anything else thats fits the analogy - perhaps maybe a python framework.<p>However, this mistake has taught me something(s) very valuable -<p>1) Don&#x27;t trade in a tried and tested framework for something like Node.js, that will open up a different level of problems altogether.<p>2) No matter what language you use, you WILL face issues at scale. Be it Node.js&#x2F;Scalatra&#x2F;Rails. You might as well face it with a tried and tested framework.<p>3) Don&#x27;t re-write your own framework in something like Go or Haskell or C or C++ or etc. thinking it will be scalable, etc.<p>You will -<p>a) Waste massive amounts of time re-inventing the wheel,<p>b) Open yourself to possibly dangerous security vulnerabilities (Eg: Handling encrypted cookies),<p>c) Waste your time on things that don&#x27;t really matter instead of on something that actually matters - The product itself.<p>4) Anything that you can scale by throwing more money at it is for the win[1]<p>Why am I talking about scalability, when the discussion is about Async. vs Sync. programming? Because of the reasons many people cite using Node.Js and the like. It&#x27;s just not worth it. Focus on the product first and the architecture later. This comes from someone who wasted a year of his life doing everything above.<p>[1]<a href="http://highscalability.com/blog/2013/4/15/scaling-pinterest-from-0-to-10s-of-billions-of-page-views-a.html" rel="nofollow">http:&#x2F;&#x2F;highscalability.com&#x2F;blog&#x2F;2013&#x2F;4&#x2F;15&#x2F;scaling-pinterest-...</a>
评论 #7400745 未加载
angersock大约 11 年前
So, here&#x27;s how I think about it:<p>Any program, of any type, has a synchronous story to it: data came in, then this happened to it, then this happened to it, then it left. If you follow the program execution, this is how it works.<p>It&#x27;s very easy to reason about, right? And it&#x27;s very easy to program this way.<p>One of the biggest breakthroughs in computer engineering was the idea of multiple concurrent processes (and nevermind that behind the scenes they were still running on a single processor!), and then later still true concurrent multi-processor architectures.<p>We developed operating systems and compilers and runtimes <i>specifically</i> to let us take advantage of that without the having to break from easy-to-reason-about synchronous code.<p>~<p>Node said, hell with it, everything is async all the time. This is really annoying at first, because there are many many times where sync is the best way to reason about something.<p>That said, there is some beauty in such a hard-line approach: if you are truly async, handling an error is the same as handling a task which takes too long. Once you&#x27;ve paid that price properly, you&#x27;re fine. (This is also what makes Erlang kind of cool.)<p>The big frustration is that there really ought to be a way of writing synchronous-looking Javascript code (ES5) which--behind the scenes!--is multiplexed and made to run concurrently and without blocking. The mechanisms are all there for programmers to deal with exceptional failures (exceptions, anyone?), and so are synchronization points (functions having multiple arguments should probably join on the evaluation of those arguments before being invoked--that&#x27;s something the interpreter should be doing already).<p>I guess what I&#x27;m saying is...why don&#x27;t JS interpreters do lazy evaluation and late binding?
EGreg大约 11 年前
Um, am I the only one who considers Node.js a beautiful tool suited for developing servers?<p>Why async by default? Because defaults should encourage best practices. It can handle C10K problem out of the box. With libraries like Q, the code can actually be rather easy to follow and maintain.<p>One of the biggest reasons why a multi-user server should be coded in async-by-default style is as follows: often, you want to obtain objects and not care about how they are obtained. In procedural languages, this isn&#x27;t possible. Consider the following challenges:<p>1) Query sent to 10 different shards, wait until they all return, combine the results in the app, and then use them. In a synchronous language, you HAVE TO go to one shard, then another, then another, and the time is 10x longer. In an async style, it&#x27;s only as long as the longest query!<p>2) Some of the objects may have already been cached, whereas others need to be obtained. In addition, the ones that need to be obtained shouldn&#x27;t be requested more than once at the same time, but callbacks should be placed on a waiting list.<p>3) Various parts of your code (e.g. from different requests) might want to request the same object. Not only that, but you might want to batch your requests. That is to say, wait 10 milliseconds and see if any other (unrelated) parts of your code also want to grab some objects from the same DB table. Suddenly you are issuing a lot less queries because you can build middleware like this easily in JS. Not so in PHP for example - I would know. A lot is wasted there.<p>4) Let&#x27;s consider #1 some more. The queries may go to other HTTP endpoints - do you really want to wait that long for I&#x2F;O? Furthermore, even if they are going to local MySQL shards, your site becomes slower with an extra factor of O(log n) with the number of users. Kind of like when you use a relational database instead of a graph database for one-degree-away lookups. It could have been O(1) but instead you introduced another factor of O(log n). Not terrible, but certainly gives you a 5-20x cost down the line.
评论 #7399656 未加载
jwarkentin大约 11 年前
It seems that OP thinks the asynchronous nature of JavaScript was meant as a performance optimization. Let&#x27;s go back to its origins. It was originally a scripting language for the browser. If it were to be synchronous and&#x2F;or allow blocking things, such as `sleep()` or whatever else, it would have created an unusable web experience. Web pages would be constantly locking up. It&#x27;s only recently that it&#x27;s moved to the server where the asynchronicity on I&#x2F;O isn&#x27;t so mandatory.<p>I personally still think it&#x27;s a good thing, but that could definitely be debated on the server side. Unfortunately, if you want to have the advantage of writing one code base that can run on the browser or server, then it must work the same in both places.
meryn大约 11 年前
I posted this as a comment on the gist:<p>It&#x27;s not about performance, it&#x27;s about &lt;del&gt;parallelism&lt;&#x2F;del&gt; concurrency.<p>If you don&#x27;t care for Node&#x27;s ability to handle multiple requests &lt;del&gt;in parallel&lt;&#x2F;del&gt; concurrently, with a single process with only one thread, than you might not have a need for Node at all. Why not use Ruby or Python?<p>If you really want to force Node into being a dumb scripting engine, you could use the various sync functions that Node.js provides. Problem is, they block the entire thread. But if you want to, you can. And I believe with some clever hacks, you can use the blocking nature of (for example) the fs sync functions to make other calls (including http requests) synchronous as well. But unless you use Node to build something that&#x27;s not a server (people build command line tools with it as well), I don&#x27;t think you want to.<p>By using synchronous functions, everything Node is built for will go down the drain. Everything done will be done in sequence, and during the time the sequence of operations has not finished, the Node runtime will be unavailable to serve any requests.<p>I suggest you look into promises as a somewhat saner way to deal with asynchronicity than callbacks, although you can pretty far with just the Async library. The future might be in Generators, a new feature of EcmaScript 6. This is available in V8. You can use this in Node 0.11 (unstable) if you use the --harmony flag. See here for a nice writeup: <a href="http://blogs.atlassian.com/2013/11/harmony-generators-and-promises-for-node-js-async-fun-and-profit/" rel="nofollow">http:&#x2F;&#x2F;blogs.atlassian.com&#x2F;2013&#x2F;11&#x2F;harmony-generators-and-pr...</a>
评论 #7399431 未加载
sergiotapia大约 11 年前
<a href="https://www.youtube.com/watch?v=bzkRVzciAZg" rel="nofollow">https:&#x2F;&#x2F;www.youtube.com&#x2F;watch?v=bzkRVzciAZg</a>
morganherlocker大约 11 年前
&gt; If asynchronous code is harder to reason about, why would we elect to live in a world where it is the default?<p>Because if you do not make it the default, then most libraries you use will make the choice for you by going sync.
mattgreenrocks大约 11 年前
My big beef with Node.js: it could have avoided the sync&#x2F;async split entirely by using a synchronous facade atop an asynchronous runtime...but it didn&#x27;t. Why would you create an entire server platform and <i>not</i> use the chance to simplify the most common use case: fetching data from a database?<p>I see as a great opportunity completely squandered so that it would cater to the masses: &quot;you don&#x27;t have to learn anything new!&quot;<p>Sometimes I think web tech <i>likes</i> being as shoddy and thrown-together as possible.
Cless大约 11 年前
You can have an async implementation and synchronous code. <a href="http://meteor.com" rel="nofollow">http:&#x2F;&#x2F;meteor.com</a> does that part quite nicely. The compiler or runtime should be handling this kind of cruft for us in most cases. Just because using Brainfuck might result in theoretically faster code than Ruby doesn&#x27;t mean we should be writing our server in Brainfuck.
mistercow大约 11 年前
&gt;but I&#x27;d be very curious to hear a defense of &quot;async-first&quot; thinking for problems that are typically solved on the server-side<p>Because if your web server blocks every time it accesses a file, or talks to a database, or communicates over the network, then it won&#x27;t take many requests at the same time before it&#x27;s completely bogged down.
clux大约 11 年前
Asynchronicity isn&#x27;t an optimization, it&#x27;s a simplification. Blocking code and threads are hard to reason about, but callbacks are simple. You still have to deal with errors in a synchronous world, and an evented system allows you to deal with branching event possibilities sanely.
评论 #7399398 未加载
WhiteNoiz3大约 11 年前
My argument would be that if you go &#x27;sync first, async if you feel like it&#x27;, everyone will just do sync, because it <i>is</i> easier conceptually (or atleast more familiar to a lot of people).
anuraj大约 11 年前
In browser content may need to be asynchronous, but HTTP is request&#x2F;response - nothing asynchronous. Half the web (or more) is not about feeding the browser. Use asynchronicity where needed.
deividy大约 11 年前
Am I the only dev in the world that loves async?
schrijver大约 11 年前
As a designer I have been trying to dig this stuff. Server side JS seems like a huge win for all kinds of small websites and interesting ui experiments, because one can stay in one language and avoid code duplication.<p>Yet in trying to set up some experiments that use a server-side git integration, I bumped into the kind of code described in this thread, and I find it super difficult to understand the async way of doing things.<p>Here’s an example from the homepage of nodegit, which seem to be among the best maintained libraries that wrap libgit2. Thus I imagine it represents idiomatic node.js What the code does, is console.log details of all the repositories commits, git log style.<p><pre><code> &#x2F;&#x2F; Load in the module. var git = require(&#x27;nodegit&#x27;), async = require(&#x27;async&#x27;); &#x2F;&#x2F; Open the repository in the current directory. git.repo(&#x27;.git&#x27;, function(error, repository) { if (error) throw error; &#x2F;&#x2F; Use the master branch (a branch is the HEAD commit) repository.branch(&#x27;master&#x27;, function(error, branch) { if (error) throw error; &#x2F;&#x2F; History returns an event, and begins walking the history var history = branch.history(); &#x2F;&#x2F; History emits &#x27;commit&#x27; event for each commit in the branch&#x27;s history history.on(&#x27;commit&#x27;, function(error, commit) { &#x2F;&#x2F; Print out `git log` emulation. async.series([ function(callback) { commit.sha(callback); }, function(callback) { commit.date(callback); }, function(callback) { commit.author(function(error, author) { author.name(callback); }); }, function(callback) { commit.author(function(error, author) { author.email(callback); }); }, function(callback) { commit.message(callback); } ], function printCommit(error, results) { if (error) throw error; console.log(&#x27;SHA &#x27; + results[0]); console.log(results[1] * 1000); console.log(results[2] + &#x27; &lt;&#x27; + results[3] + &#x27;&gt;&#x27;); console.log(results[4]); }); }); }); }); </code></pre> It looks so alien to me! Instead of the tree-walking and looping constructs I know from synchronous languages, we deal with a history that returns events as it walks the tree (btw, why is it that we can launch the history before we attach the event?). Then we have to actually import the ‘async’ module, because, uhm, we want to specify an order by which the different parts of the message gets logged.<p>How then the actual callbacks work, I’d be happy if someone can explain that to me—why do I pass a function to an attribute of the object? Why don‘t I just return the value?<p>Because the code is not written in a lineair way, I have to keep looking back and forth between callbacks to get a mental picture of what it does.<p>For the record, what this translates to as synchronous Python:<p><pre><code> from pygit2 import Repository, GIT_SORT_TOPOLOGICAL repo = Repository(&#x27;.git&#x27;) for commit in repo.walk(repo.head.target, GIT_SORT_TOPOLOGICAL): print &#x27;SHA %s&#x27; % commit.hex print commit.commit_time * 1000 print &#x27;%s &lt;%s&gt;&#x27; % (commit.author.name, commit.author.email) print commit.message </code></pre> I imagine that, as some of the commenters note, I will be able to start reading the async style if I get enough exposure to it. I wonder though, if it does not make the barrier to entry for server-side JavaScript too high for non-full-time programmers.<p>In that sense it is interesting that the Meteor team chose to use the package Fibers, that allows one to write node.js in a procedural style. I imagine something like that is necessary for server side JS to become really mainstream in web design…
notastartup大约 11 年前
The creator of Node.js said it best himself, that his afraid people associate Node.js with scalability out of the box due to the single threaded asynchronous nature, that there exists something magical about it that would suddenly make your app scalable because it&#x27;s riddled with async code.<p>I now use Flask and Python instead of Node.js and it&#x27;s a total pain reliever. Not having to deal with Javascript is a win on the server side (JS on client side is enough) and the python stack is good enough to handle every bit of Node.js<p>Truth is, Node.js is in a bubble. I find it that even people who have never programmed before insisting that their new website be written in Node.js.... It reminded me of the dot com bubble, when your grandma would explain to you her rationale for buying dot com stocks (they had no idea).
sheetjs大约 11 年前
node.js does not impose it for everything. Every command in the fs library that has a natural synchronous interpretation (like reading a file, writing a file, ...) has a sync equivalent (readFileSync, writeFileSync, ...)
评论 #7399215 未加载
评论 #7399158 未加载