Closed z-vr closed 6 years ago
fast-async
, unlike nodent
(the compiler that actually does the transpiling) forces you to use Promises
for compatibility reasons. Use a common Promises
implementation and include it in your scripts. My recommendation (and used by the nodent-runtime
) is https://github.com/bluejava/zousan
...or I think there is a Babel plugin that ensures Promise
is defined globally if necessary
but I saw that Zousan was in my code when bundled, so why is it there if it's not using it? Also what is the purpose of nodent-runtime
then?
I thought I could do
new webpack.ProvidePlugin({
Promise: 'nodent-runtime/zousan',
}),
but it results in an error that promise is not a function. Is there any way to reuse bundled zousan
or not bundle it with nodent-runtime
?
Sorry for noob questions, it's kind of confusing.
I'm not really familiar enough with WebPack to know how to provide a global value for Promise. My hack would be the line early in your initialisation code:
window.Promise = window.Promise || require('nodent-runtime/zousan')();
Note the brackets at the end - zousan.js provides a function (which can take a scheduler function), so you need to call it to get a reference to Promise. Alternatively, include the following lines in each file that requires support for Promises:
import getPromise from 'nodent-runtime/zousan' ;
const Promise = getPromise() ;
This doesn't pollute the global scope, but the convention seems to be a global polyfill for Promise
is acceptable
ok your vendored version does not have .all
method, so I'll use actual Zousan. The thing I'm still not sure about, is whether promises: false
should not work without Promises? and thanks for awesome lib. Would it be possible to require latest zousan
in nodent-runtime
so that dependencies could be dedupped -- or its full functionality is not required there? Although it's 1.65KB
in nodent-runtime
compared to 2.49KB
in the zousan
, when put together they take more than if only one was used in a project due to reusing the same package.
I checked the code, and promises: false
should be supported, and then it uses the stripped down Zousan in nodent-runtime (which does some other things as well). You can see an example of the promise-free code generated [here](http://nodent.mailed.me.uk/#async%20function%20tellYouLater(sayWhat)%20%7B%0A%20%20%20%20%2F%2F%20Do%20something%20asynchronous%2C%20such%20as%20DB%20access%2C%20web%20access%2C%20etc.%0A%20%20%20%20return%20%22I%20said%3A%20%22%2BsayWhat%3B%0A%7D%0A%0Aasync%20function%20test()%20%7B%0A%20%20%20%20return%20tellYouLater(%22I'll%20tell%20you%20later%22)%20%3B%0A%7D%0A%0Aconsole.log(await%20test())%3B%0A~options~%7B%22mode%22%3A%22es5%22%2C%22promiseType%22%3A%22Zousan%22%2C%22noRuntime%22%3Afalse%2C%22es6target%22%3Afalse%2C%22wrapAwait%22%3Afalse%2C%22spec%22%3Afalse%7D) - there are no references to Promises in the generated code as they are internally supplied by the $asyncbind
runtime function.
I'm reasonably convinced it works. From the fast-async
installation (probably in your node_modules
), try the the following:
npm test # This will install the babel-cli
cd tests
./node_modules/babel-cli/bin/babel.js ./test-input.js # Compile "test-input.js" and show the output
Now edit the "package.json" in the same directory (tests) to have the options you want. Mine look like:
"babel": {
"plugins": [
[
"..",
{
"compiler":{
"promises": false
},
"useRuntimeModule": true
}
]
]
}
(Note: we use '..' for the plugin name here because we're testing the plugin in the parent directory - in your project it should say fast-async
)
Running the command line ./node_modules/babel-cli/bin/babel.js ./test-input.js
generates code with no Promises (except the one explicitly in the original input file)
import _default from "nodent-runtime";
/* fast-async test file - it gets compiled by Babel using fast-async and other async-await implementations to measure performance */
function pause() {
return new Promise(function ($return, $error) {
setTimeout(function () {
return $return(0);
}, 0);
});
}
function doNothing() {
return function ($return, $error) {
return $return();
}.$asyncbind(this, true);
}
function test() {
return function ($return, $error) {
var t, j, i;
t = Date.now();
j = 0;
return Function.$asyncbind.trampoline(this, $Loop_1_exit, $Loop_1_step, $error, true)($Loop_1);
function $Loop_1() {
if (j < 500) {
i = 0;
return Function.$asyncbind.trampoline(this, $Loop_3_exit, $Loop_3_step, $error, false)($Loop_3);
function $Loop_3() {
if (i < 500) {
return doNothing().then(function ($await_5) {
return $Loop_3_step;
}.$asyncbind(this, $error), $error);
} else return [1];
}
function $Loop_3_step() {
i++;
return $Loop_3;
}
function $Loop_3_exit() {
return pause().then(function ($await_6) {
return $Loop_1_step;
}.$asyncbind(this, $error), $error);
}
} else return [1];
}
function $Loop_1_step() {
j++;
return $Loop_1;
}
function $Loop_1_exit() {
return $return("Finished " + 500 * 500 + " async/awaits in " + (Date.now() - t) + "ms");
}
}.$asyncbind(this, true);
}
test().then(resolve, reject);
/* If you see this, then test-input.js was compiled by babel-cli. Things to check are that there's an import at the top for nodent-runtime, and lots of symbols starting with $ */
@matAtWork thanks for the detailed instructions and ah OK you're right, the problem I had was because Webpack's dynamic loading requires Promise
. On the other hand, would you consider implementing Promise.all
in fast-async
?
I probably won't implement Promise.all in the runtime, since the purpose of the runtime is to provide the smallest, fastest Promise/A+ implementation as required by the spec for async
and await
. If you need more capable Promises, there are lots of libraries and native implementations that will also work with nodent
.
If you really want that function, and no more, you can always use the implementation from https://github.com/bluejava/zousan/blob/master/src/zousan.js#L253
OK sorry I got confused again, I thought fast-async
was failing to compile my Promise.all([Promise.resolve(), Promise.reject()])
into nodent-runtime runnable code, but apparently it's not what it does!
Nope. It does compiles the async
and await
keywords, that cannot be implemented at run time. Promise
is simply a global variable - it's not a language keyword - and is implemented at run time by a number of well-known libraries.
@matAtWork promises:true // Use nodent's "Promises" mode. Set to false if your runtime environment does not support Promises (default: true)
-- this made me think this plugin does some magik :P
Resolved in https://github.com/MatAtBread/fast-async/pull/48
How do I use this for IE9? I have in
.babelrc
:and even
import nodent-runtime
in my main file, but I keep seeing thatPromise is undefined
in IE. Could you please explain how to use it :(( it's so frustrating -- do I need to update webpack config to provide globalPromise
?