New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Convert Promise to async function #202
Comments
Also:
should be changed to:
|
The first example looks weird. The The other proposal should automatically work once we have support for parsing the async-await syntax, and that's really the part behind which all of this is waiting. It also requires Recast to support that additional syntax - it allows to swap the parser and use e.g. babylon, but I think it only really supports syntax up to ES2016. |
@nene Sorry, the first example was some quick one-off code. Maybe this blog post has better examples: https://hacks.mozilla.org/2016/12/asyncawait-arrive-in-firefox/ |
instead of nested Promise callbacks, we want async/await |
@nene Babylon supports everything :D https://github.com/tunnckoCore/parse-function/blob/master/test.js is proof that it works for |
@tunnckoCore Ah, I guess my comment was pretty ambiguous. My concern wasn't about babylon, but about Recast supporting the things babylon supports. |
@nene recast should support everything Babel does after my PR to update it to support Babel 6 changes; if not we can make a issue/pr |
Ah, that's great to hear. I definitely have to try it out then. |
Now that Node.js supports async natively, I can't wait to convert from the explicit Conversion of |
I've thought so, too, and started implementing a transformation. It turns out, when chaining this becomes very hard, because the handler functions can be arbitrarily complex. So for the general case, all you can do is replace the .then call with await and then call the handler (still inline) with the result. It would look like this: /* maybe return and/or chain */promise.then(function(result) { /* complex code */ }) becomes let result = await promise;
/* maybe return and/or chain */(function (result) { /* complex code */ })(result); Now usually, what is marked as |
Well, I can only speak for Lebab, which doesn't have anything like that. One of the main complexities with promise to await conversion, is that promise execution is asynchronous, while So, when you have:
You can't simply convert it to:
I don't even know what a good conversion result would be. |
You're right, it's only possible to convert function(url) {
return fetch(url).then(doSomething);
} This can simply be converted into async function(url) {
return doSomething(await fetch(url));
} However, that's not the case I'm looking at (and I'm not even sure I'd want to do this conversion). What I'm looking at is when function(url) {
return fetch(url).then(result => { return { from: url, got: result}; });
} So far, I believe if the outer function is written properly to return the Promise, the last (or only) handler function can be inlined (except for variable name collisions). So the last example can be converted to this: async function(url) {
let result = await fetch(url);
return { from: url, got: result};
} Yes, that invalidates/solves the example in my previous comment. However, once we get to chaining, I'm back to the previous solution. Consider this example: function(url) {
return fetch(url)
.then(result => { return result.json(); })
.then(result2 => { return { from: url, got: result2}; });
} So far I've implemented a simple case that checks if the function only returns as its last statement and inlines it explicitly, assigning the return value to the next function's argument. That converts the example to this: async function(url) {
let result = await fetch(url);
let result2 = await result.json();
return { from: url, got: result2};
} There are still a couple of questions I'm wondering about (sorry if they don't directly concern this feature):
I hope to find more time to work on this and eventually release something, but I can't promise anything. In the meantime I'd be happy to hear other thoughts on this. |
This last example of yours looks pretty neat.
Not sure I really understand what sort of optimizing-away you have in mind.
My goal has always been to have an output that would most resemble the code one would write himself. Also, the code produced by Lebab should be improvement over the existing code - if the result is harder to read than the original, then such a transform is not really worth having. The labeled blocks and IIFE-s look more like some compiler output - so I'd steer away from these. As the main merit of async/await is the ability to write your code in synchronous-looking manner, I think that's the kind of output we should strive for in here. |
I'm pleased to announce a new codemod I developed for this. It's still a bit of a work in progress, but it's getting pretty baller. You may be interested in integrating it into lebab. (Although the README shows how to use it with jscodeshift, the transform is actually implemented with pure babel 7). https://github.com/codemodsquad/asyncify Right now if you want to see examples look in the tests. I'll plan on making a try-it site in the next few days. |
Input:
Expected output:
The text was updated successfully, but these errors were encountered: