MatAtBread / fast-async

605 stars 21 forks source link

How to create Bluebird promises from async functions #29

Closed Rush closed 7 years ago

Rush commented 7 years ago

Given the below code, how to configure fast-async/nodent to return bluebird promises?

import Promise from 'bluebird'; 

async function foo() {
  return 'bar';
}
// where .delay is provided by bluebird
foo().delay(3000).then(() => {

});
Rush commented 7 years ago

And basically, I don't care how promises internally work in nodent. I'd just like the return value to come from bluebird like so return Promise.resolve(returnValue) where Promise comes from bluebird.

Rush commented 7 years ago
wget http://x.rushbase.net/3f75b88cc659b223343c88f1eddd37ece3ceab6c/babel-fast-async-test.zip
unzip babel-fast-async-test.zip
cd babel-fast-async-test
node -r babel-register index.js

Note: when using require instead of import bluebird promise is returned.

MatAtBread commented 7 years ago

Nodent doesn't care what type of promise you define (assuming you're using -promise mode, which is the default). If you set Promise to be bluebird's implementation, that's what you'll get, as it simply calls new Promise(...).

However, be aware that the standard implementation (eg in V8 5.4) does not work this way, and always used the native Promise implementation, so code written in the style you're proposing won't run on native async/await implementations without transpilation.

Rush commented 7 years ago

The problem is that babel re-writes Promise symbol to something else if using import and nodent ends up not using my implementation of choice (probably due to how fast-async injects itself). Could you add an option to specify explicitly the promise library to use? Also, I do appreciate Zousans's performance but I do need some of bluebird features so preferably all the internals of async functions should be using Zousan and only the external interface of calling an async function should be the implementation of choice like bluebird. Is it doable?

matAtWork commented 7 years ago

I'll take a quick look at how babel mangles Promises, but fast-async/nodent don't use any particular Promise implementation in "use nodent-promises" mode - it just references the global symbol "Promise" in the same way that your own code would. It would seem you need an option to stop babel over-writing "Promise" if that is what's happening. fast-async only falls back to Zousan if you're using "-es7" mode, not the other modes.

matAtWork commented 7 years ago

The solution is to put fast-async before any modules that mangle Promises. I changed the .bablerc (see below) and it seems to work. I don't know what the other plugins/presets are doing, but at least one of them is over-writing "Promise".

{
  "presets": ["es2015-node6"],
  "plugins": [
        ["fast-async", {"useRuntimeModule": true}],
    "transform-decorators-legacy", "transform-class-properties", "transform-es2015-modules-commonjs", "transform-strict-mode", "transform-es2015-spread", "transform-es2015-destructuring",
    "transform-es2015-block-scoping"
  ]
}
Rush commented 7 years ago

Thank you, this indeed works. It might be a good tip to put this information into README.