-
-
Notifications
You must be signed in to change notification settings - Fork 32.2k
Description
No, I am not writing this from a mental hospital, please read till the bottom.
The purpose of this is to discourage using *Sync
versions of the methods that could be async.
I propose to put all or at least a part of *Sync
methods behind a runtime flag in some future major version of io.js and to split documentation, moving all *Sync
methods to a separate page. This of course would be semver-major.
Atm, there are *Sync
methods defined in zlib
, fs
, child_process
, crypto
modules and additionaly used in repl
and module
modules.
To allow usage inside io.js itself (i.e. for require
), they could be moved to «private» methods (beginning with a _
sign).
-
*Sync
methods suggest bad practices (see 2), but when someone with full understanding of the consequences needs them, they could be constructed from userspace. See https://github.com/abbr/deasync, it creates synchronous methods from async methods.
If deasync module is not good enough for this, this could be done when there is would be a good enough solution. -
When a newcomer begins writing something using io.js, he or she goes to the documentation looking how to do something, sees
*Sync
methods without any warnings there and almost certanly begins with using them, because that's what he or she is used to. That's easier for a newcomer than spending a few minutes reading how he or she should actually do stuff. And don't blame the newcomer, it's the presense of*Sync
methods in the documentation that suggests to him or her that it's an ok way to do things. This results in a big pile of bad code by the time when the person understands that it should be rewritten. And people don't like to rewrite code for no visible reson, leaving this code to be legacy (see 3). -
When someone writes synchronous code (see 2) it limits how he or she can use async functions without rewriting most part of the logic, so he or she comes complaining about that there should be a
*Sync
version of everything out there (as the presense of*Sync
versions in the core suggests it). See Is there a sync version encapsulating libmagic in node.js ? mscdex/mmmagic#32 and motivation behind https://github.com/abbr/deasync. -
It's completely broken either way. Even for «simple one-time scripts». See zlib: memory leak with gunzipSync #1479 — a person was doing something like
files.forEach( …zlib.gzipSync(…) …)
, in what I suppose was a simple script. What could possibly go wrong? Memory usage has gone completely bad in his script. And even manual calls togc()
do not help. Testcase:'use strict'; var zlib = require('zlib'); var data = 'abcdefghijklmnopqrstuvwxyz'; var gzipped = zlib.gzipSync(data); function call() { var contents = zlib.gunzipSync(gzipped); } for (var i = 0; i < 100000; i++) { call(); if (i % 1000 === 0) { gc();gc();gc();gc(); console.log(i + ' ' + JSON.stringify(process.memoryUsage())); } }
-
People go to the doc, see
*Sync
versions (see 2), use them — then everyone are telling them that they are using io.js wrong just based on that fact: gripe: deprecating fs.exists/existsSync #1592 (comment).if you're using existsSync inside your server I'd argue you're not using io.js correctly to begin with
-
One can argue again that using
*Sync
versions of methods is ok in scripts and that that's simplier, but:- See 4.
- For one-time, throw-away scripts you can turn that flag on.
- Promises-based code is as clean as
*Sync
-based code. Promises-based code with accurate error handling is much cleaner that*Sync
-based code with accurate error handling. Using Promisify won't be needed once Promises go to the core (see Feature Request: Every async function returns Promise #11).
This will require all public modules that are using *Sync
methods either to rewrite things using async methods or require/include something like https://github.com/abbr/deasync to be compatible.
This can be done separately for various core modules/methods. For example, zlib.*Sync
are maybe the worst of them and it looks to me that they are not actively used in public modules.