{"action":"created","issue":{"url":"https://api.github.com/repos/iojs/io.js/issues/1665","labels_url":"https://api.github.com/repos/iojs/io.js/issues/1665/labels{/name}","comments_url":"https://api.github.com/repos/iojs/io.js/issues/1665/comments","events_url":"https://api.github.com/repos/iojs/io.js/issues/1665/events","html_url":"https://github.com/iojs/io.js/issues/1665","id":74659974,"number":1665,"title":"Put `*Sync` methods behind a flag in some future major version","user":{"login":"ChALkeR","id":291301,"avatar_url":"https://avatars.githubusercontent.com/u/291301?v=3","gravatar_id":"","url":"https://api.github.com/users/ChALkeR","html_url":"https://github.com/ChALkeR","followers_url":"https://api.github.com/users/ChALkeR/followers","following_url":"https://api.github.com/users/ChALkeR/following{/other_user}","gists_url":"https://api.github.com/users/ChALkeR/gists{/gist_id}","starred_url":"https://api.github.com/users/ChALkeR/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/ChALkeR/subscriptions","organizations_url":"https://api.github.com/users/ChALkeR/orgs","repos_url":"https://api.github.com/users/ChALkeR/repos","events_url":"https://api.github.com/users/ChALkeR/events{/privacy}","received_events_url":"https://api.github.com/users/ChALkeR/received_events","type":"User","site_admin":false},"labels":[{"url":"https://api.github.com/repos/iojs/io.js/labels/discuss","name":"discuss","color":"02d7e1"},{"url":"https://api.github.com/repos/iojs/io.js/labels/future","name":"future","color":"e102d8"}],"state":"open","locked":false,"assignee":null,"milestone":null,"comments":14,"created_at":"2015-05-09T12:16:47Z","updated_at":"2015-05-09T21:23:48Z","closed_at":null,"body":"*No, I am not writing this from a mental hospital, please read till the bottom.*\r\n\r\nThe purpose of this is to discourage using `*Sync` versions of the methods that could be async.\r\n\r\nI 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.\r\n\r\nAtm, there are `*Sync` methods defined in `zlib`, `fs`, `child_process`, `crypto` modules and additionaly used in `repl` and `module` modules.\r\nTo allow usage inside io.js itself (i.e. for `require`), they could be moved to «private» methods (beginning with a `_` sign).\r\n\r\n1. `*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.\r\n*If deasync module is not good enough for this, this could be done when there is would be a good enough solution.*\r\n2. 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 is used to. That's easier for the newcomer that 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).\r\n3. 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 https://github.com/mscdex/mmmagic/issues/32 and motivation behind https://github.com/abbr/deasync. \r\n4. It's completely broken either way. Even for «simple one-time scripts». See https://github.com/iojs/io.js/issues/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 to `gc()` do not help. Testcase:\r\n ```javascript\r\n 'use strict';\r\n\r\n var zlib = require('zlib');\r\n var data = 'abcdefghijklmnopqrstuvwxyz';\r\n var gzipped = zlib.gzipSync(data);\r\n\r\n function call() {\r\n    var contents = zlib.gunzipSync(gzipped);\r\n }\r\n\r\n for (var i = 0; i < 100000; i++) {\r\n     call();\r\n     if (i % 1000 === 0) {\r\n         gc();gc();gc();gc();\r\n         console.log(i + ' ' + JSON.stringify(process.memoryUsage()));\r\n     }\r\n }\r\n```\r\n5. 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: https://github.com/iojs/io.js/issues/1592#issuecomment-100448962.\r\n\r\n > if you're using existsSync inside your server I'd argue you're not using io.js correctly to begin with\r\n\r\n6. One can argue again that using `*Sync` versions of methods is ok in scripts and that that's simplier, but:\r\n 1. See 4.\r\n 2. For one-time, throw-away scripts you can turn that flag on.\r\n 3. 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 https://github.com/iojs/io.js/issues/11).\r\n\r\nThis 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.\r\n\r\nThis 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."},"comment":{"url":"https://api.github.com/repos/iojs/io.js/issues/comments/100550979","html_url":"https://github.com/iojs/io.js/issues/1665#issuecomment-100550979","issue_url":"https://api.github.com/repos/iojs/io.js/issues/1665","id":100550979,"user":{"login":"benjamingr","id":1315533,"avatar_url":"https://avatars.githubusercontent.com/u/1315533?v=3","gravatar_id":"","url":"https://api.github.com/users/benjamingr","html_url":"https://github.com/benjamingr","followers_url":"https://api.github.com/users/benjamingr/followers","following_url":"https://api.github.com/users/benjamingr/following{/other_user}","gists_url":"https://api.github.com/users/benjamingr/gists{/gist_id}","starred_url":"https://api.github.com/users/benjamingr/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/benjamingr/subscriptions","organizations_url":"https://api.github.com/users/benjamingr/orgs","repos_url":"https://api.github.com/users/benjamingr/repos","events_url":"https://api.github.com/users/benjamingr/events{/privacy}","received_events_url":"https://api.github.com/users/benjamingr/received_events","type":"User","site_admin":false},"created_at":"2015-05-09T21:23:48Z","updated_at":"2015-05-09T21:23:48Z","body":"I think we're forgetting how much userland code this sort of hard-deprecation and putting behind a flag breaks. Tons of packages use the `Sync` variant.\r\n\r\nWouldn't it be nicer to just discourage them in the docs more or soft-deprecate them? Our developers aren't retards, most io developers understand what blocking and non-blocking code means. Removing these just seems cruel and I'm not really sure what problem it actually solves."}}