Promise is not resolved nor rejected

It’s been a while since I last wrote JavaScript, and it has improved a lot. A lot of ES6 features are already included in Node v6+, like promise, string template literal, if you write a command line tool, tools like babel is no longer needed. I decided to write a static about us & blog site generator using these cool new features. However I got a strange bug when using Promise, it is not resolved nor rejected.

As we know, callback is used very often in JavaScript, like the following

setTimeout(()=>{console.log(‘haha’);}, 200)

Things can become pretty ugly if you start to have a lot of callbacks, that’s why promise is introduced. (I knew promise when I started using angularjs, it provided a minimal implementation $q) The detail syntax can be found in MDN. The bug code snippet is provided below.

render.renderByFile(args[0], {title: 'abc'}).then((out)=> {
if (args.length === 1 || flags.o) {
logger.info(out);
}
if (args.length == 2) {
logger.warn('TODO: write output to file', {file: args[1]});
}
}).catch((e)=> {
logger.error(e);
});

I never see the log when the command line application runs ,but in the unit test, everything is working. So my first thought is some libraries used in the command line framework has dependency for promise libraries that broke Node’s built-in promise or broke console.log. I removed the logger to verify this, but everything is the same. Then I added a console.log right after the render.renderByFile, it did log. However when I added a setTimeout for log, it did not log. Thus I got the answer, the command line application exited before the asynchronous call finished. Comment out the line calling process.exit(0), the promise is working as expected.

In general, if your promise callback is not resolved nor rejected, it means it is never executed, somewhere in your code called process.exit(code) because you treat every function call as synchronous. However in NodeJS, you called a function and checked its return value does not mean you are done with it, that function may invoke some asynchronous functions that include IO related operations, like reading file, calling remote API. So don’t use process.exit everywhere, unless you know everything is finished or it’s a fatal error.

One clap, two clap, three clap, forty?

By clapping more or less, you can signal to us which stories really stand out.