In the version of node 6.5.0 that I am running, the repl does support quite a few things already - which is awesome. One thing I came to miss when trying things out though is that the yield
(as often used before await
and/or the await
keyword. If yield
would be available like with co
or await
would be available like in the concept then async code would become easy to test in the REPL.
@martinheidegger It already is if you run a generator function, I'm not 100 sure what you are asking.
Could you provide an example?
@Fishrock123 I think the idea is that the default repl wraps the code being run in a generator/async function so that the following works:
> var x = await Promise.resolve(1); x
1
~=
async () => {
return eval(`var x = await Promise.resolve(1); x`);
}
await
seems reasonable, particularly if modules get it at the top level, but not gonna bite on special casing yield
.
@Fishrock123 @bmeck Explained my request better than me.
@bmeck I am in agreement that await
seems more reasonable, the only reason I mentioned yield is because async/await seemed like an unfinished feature at this point.
My personal example is working with nodegit
> var git = require('nodegit')
undefined
> var repo = await git.getRepo('.')
undefined
> await repo.getCommit(sha)
Commit { repo: Repository {} }
@martinheidegger async/await functions were accepted in July : https://github.com/tc39/proposals/blob/master/finished-proposals.md
+1 for such a feature. It would make it much easier to work with Promise-based APIs
blocked on v8 giving us unflagged async/await functions at the very least.
I wonder if a --require module
could appropriately extend the built-in repl?
@Fishrock123 well modules have not fully landed top level await in spec (proposal in september?) so the module parser in v8 won't land the await outside of async functions for a while still.
I mean for yield
.
This is how I implemented in my electron based REPL.
const awaitMatcher = /^(?:\s*(?:(?:let|var|const)\s)?\s*([^=]+)=\s*|^\s*)(await\s[\s\S]*)/;
const asyncWrapper = (code, binder) => {
let assign = binder ? `root.${binder} = ` : '';
return `(function(){ async function _wrap() { return ${assign}${code} } return _wrap();})()`;
};
// match & transform
const match = input.match(awaitMatcher);
if(match) {
input = `${asyncWrapper(match[2], match[1])}`;
}
little workaround / hack:
await=promise=>{
ret = undefined
promise.then(response=>ret=response)
while(ret === undefined) {require('deasync').runLoopOnce();}
return ret
}
or
await=async function(promise){
result=await promise // result now available via side effect (workaround)
return result // still PROMISE in return!??! but ok otherwise
}
or just
await=promise=>promise.then(x=>result=x)
of course the proposed addition of await
to the REPL would be way better!
@princejwesley how can I add your implementation to node repl?
I saw this as well: https://github.com/paulserraino/babel-repl
but it does not support await syntax yet
cc @paulserraino
@martinheidegger what is the link for your personal working example of here: https://github.com/nodejs/node/issues/8382#issuecomment-244389612
@sibelius Something like this
@sibelius Oh: I am afraid this is a misunderstanding: this is an example of how i _would love it to work_.
@princejwesley it does work tks for the awesome work
@martinheidegger u should try @princejwesley gist
I was looking for similar solusion as well and I made this after I saw pannous's comment.
Now I'm happy with testing nodegit in REPL.
> syncPromise(require('nodegit')).getRepo('.').o.getCommit(sha).o
Commit { repo: Repository {} }
Removed blocked
because unflagged async/await have landed in master.
@joyecheung It would be nice to reference the commit.
@martinheidegger Sure, it should be PR https://github.com/nodejs/node/pull/9618 and commit https://github.com/nodejs/node/commit/2739185b790e040c3b044c577327f5d44bffad4a
@joyeecheung Awesome! Did you have a chance to test it? Does await work in the Repl?
@martinheidegger, in v7.6.0 we have updated V8 to 5.5, which makes it possible to use async functions w/o the --harmony
flag, so we can actually get started with implementing. The actual ability of using await
in the REPL hasn't been implemented yet.
Apologize for the label shuffling. Didn't realize what it was actually blocking on.
I made a small package https://www.npmjs.com/package/await-outside that you can use as
node --require await-outside/repl
or just
Hope it helps anyone
I just had a quick look at implementing this. Naively wrapping each input line with (async function() { return ${line} })()
and changing the callback trigger from cb(err, result)
to something like Promise.resolve(result).then(res => cb(null, res), cb)
works, but breaks assignments. The await-outside
module mentioned above uses a regex hack to redirect assignments to globals, but I worry about how reliable that'd be...
way too hacky if you insert multi line function etc
you might notice that the tests of await-outside do cover multi-line inputs
Hello, I wrote this quick and dirty Babel-based experiment: https://github.com/motet-a/async-repl
It works as described by @Qard, so currently variable declarations are broken. But it鈥檚 not a big deal since we could transform variable declarations into global assigments only in the _global_ scope with Babel, skipping declarations inside inner functions. It鈥檚 not perfect but it could be pretty reliable.
in the mean time you could stub repl with https://github.com/ef4/async-repl
BTW there is an open PR for await
support at https://github.com/nodejs/node/pull/15566.
Top-level await is now supported in the REPL. Closing.
Most helpful comment
@Fishrock123 I think the idea is that the default repl wraps the code being run in a generator/async function so that the following works:
~=
await
seems reasonable, particularly if modules get it at the top level, but not gonna bite on special casingyield
.