4 ms·
Now, what do you do when you want to return from that function after loadRealImage() finishes? function loadImage(src) { loadRealImage(src).then(img => /
by sillysaurus3 8y ago
Now, what do you do when you want to return from that function after loadRealImage() finishes?
function loadImage(src) {
loadRealImage(src).then(img => /*... return img from loadImage ...?*/);
}
"Just make it an async function." Well yes, but then the async nature contaminates the rest of your code. You have to make sure to set up a toplevel try-catch for every one of your async chains, for example.
What do you do when you want to have an async generator? That is, you want to both await on something, and yield N values from the function. JS makes that difficult.
There are all kinds of limitations like this, and everyone has their own favorite hacks around them. But they're hacks, not unification. And yes, hacks can be effective, but a unified framework can be tactical.
- nawgszy 8y ago>yield N values from the function const { all, the, values, you, want } = await multiValuedReturn(); ?
- sbjs 8y agoBut sillysaurus3 has a valid complaint about this line of code, that the very next line is completely blocked until multiValuedReturn() completes. A better solution is to not use `await` here, and instead use .then and Promise.all to control execution of several callbacks, while running other code synchronously. I think the problem sillysaurus3 is facing is that he wants complete convenience of the kind that async/await bring, meaning being able to execute code regardless if it finishes now or later, but always pretending that it finishes now. That's just not possible, and for good reason: some things happen now, and some things happen later, and if you need ultra-fine-grained control over what happens when, then you need to be very explicit about what's happening and how and when. It's messy and ugly, and we're working towards cleaning that up, with async/await being a great step forward, but this is inherent to the concepts of sync/async control flow, and the assembly solution is much more of a hack to solve this (if I even understand the solution correctly) than Promise/async/await/etc.
- sillysaurus3 8y agoThat's just not possible, and for good reason: some things happen now, and some things happen later, and if you need ultra-fine-grained control over what happens when, then you need to be very explicit about what's happening and how and when. Green threads. No silver bullet, but sometimes you upgrade your pistol. JS needs greenthreads. There's no reason you shouldn't just spin up a thread for every blocking context. This is arguably what async/await already does, but you don't have control over the toplevel loop. Point out where your while (userIsOnWebsite) { ... } loop is. :) Having a toplevel loop is very important for simplicity -- but even moreso for what you mention: having ultra fine-grained control, and not constantly fighting with the underlying scheduler / ecosystem.
- meowface 8y agoI've seen a lot of debate over this, but I find greenthreads so much simpler to work with and reason about, on top of keeping my code clean and completely interoperable with my synchronous code. This is off-topic from the current JavaScript discussion, but even though Python introduced "first-class" async support a while ago, I still exclusively use gevent [1] for all of my concurrency needs. It provides full greenthread support for Python. It's extremely performant on top of being simple and clean to integrate. In contrast, Python's asyncio and async/await feels needlessly verbose and tortuous, often with full rewrites or replacements of libraries required to actually take advantage of the features (e.g. https://github.com/requests/requests https://github.com/requests/requests vs. https://github.com/aio-libs/aiohttp https://github.com/aio-libs/aiohttp). With gevent, I can just put whatever code I want into a greenthread and get instant asynchronicity (excluding hiccups with a few 3rd party libraries that have network I/O in native extensions, which is rare). The one downside is it achieves its magic with standard library monkeypatching, which is pretty hideous, but it's done very seamlessly. Developers are able to write the exact same code with or without monkeypatching and not worry about what it's doing. I've never encountered an issue with the monkeypatching when using any standard or 3rd party library. [1] http://www.gevent.org/ http://www.gevent.org/
- millstone 8y ago
- deleted 8y ago[deleted]
- sbjs 8y agoSo... to solve this... you want to use what's basically goto?
- sillysaurus3 8y agoIn this case, I'd like to write blocking-style code. longjmp, however, is a crucial missing facility in JS. Emacs relies on it heavily in its design -- it's how catch / throw work, and it's why you can do things like (catch 'foo (map (fn (x) (if (= x 42) (throw 'foo x))) values)) Without longjmp, you can't do that. Just as you can't in JS. So what? Well, that means you can't write emacs, because you're limited to what JS provides you. An entire class of software is beyond your ability to write, because you cannot provide the same features that other runtimes give. This gets me started on the lack of any kind of reasonable error definitions in JS. In elisp, you define errors. Imagine you want to write some code that parses some parens -- it turns "(a b (c))" into ["a", "b", ["c"]]. What do you do when your program encounters "(a b" and then the end of the string? Throw a scan error! Not in JS. It's considered poor manners to throw errors to the people using your library. Worse, it's a pain in the ass for users to catch and respond to errors. If you use someone's library, you usually don't expect to have to wrap it in a try-catch. And the code is massive: try { operation } catch (e) { if (e instanceof ScanError) { do something else } } Contrast that with elisp: (condition-case nil operation (scan-error do something else)) There's no contest. It's way easier to write the latter than to use the tools JS gives you. But it's a cultural difference, and culture is slow to change. That's why webassembly at least gives an escape hatch.
- millstone 8y ago> Well, that means you can't write emacs, because you're limited to what JS provides you Well JS does provide this via exceptions. Second it's totally crazy that emacs depends on longjmp, which is an insane decades-old wart that ought to just quietly die. Third...does web assembly even support longjmp? I'm pretty sure it does not. > That's why webassembly at least gives an escape hatch. Escape hatch from...writing five lines instead of three?
- 8y ago