4

While i'm studying https://nodejs.org/api/process.html#process_process_nexttick_callback_arg , i'm stucked at a point. I'm quoting it below :

It is very important for APIs to be either 100% synchronous or 100% asynchronous. Consider this example:

// WARNING!  DO NOT USE!  BAD UNSAFE HAZARD!    
function maybeSync(arg, cb) {     
    if (arg) {      
        cb();       
        return;       
    }

    fs.stat('file', cb);

This API is hazardous because in the following case:

maybeSync(true, () => {       
     foo();     
});     
bar();   

It is not clear whether foo() or bar() will be called first.

I didn't understand why it is not clear whether foo() or bar() will be called first. Because arg is true and maybeSync function works synchronously. Thus everything works synchronously and foo() will be called before bar(), i think. Why this is not true for this case?

The following approach is much better:

function definitelyAsync(arg, cb) {       
    if (arg) {      
        process.nextTick(cb);       
        return;
    }

    fs.stat('file', cb);    
}
metis
  • 1,024
  • 2
  • 10
  • 26
  • 2
    It's not clear whether `foo()` or `bar()` will be called first *unless you look at the internals of the `maybeSync()` function.* And even then you don't really know what'll happen at runtime unless you can guarantee that the values you pass it will *always* be of a certain type. You should be able to rely on a particular function always being synchronous or always asynchronous without having to look at how the function is implemented. – nnnnnn Jul 02 '16 at 10:09
  • @nnnnnn , OK I got it. One more question please, what is () => { ... } in the second parameter of maybeSync() function ? I cannot search it on google :S – metis Jul 02 '16 at 10:27
  • 1
    They're called arrow functions, and are part of the new ES6 (EcmaScript 6). `() => { ... }` is the shorthand equivalent of `function() { ... }` - but beware there are also some differences in scope. – Mihai Potra Jul 02 '16 at 10:56
  • Have a look at [Are callbacks in node.js either always asynchronous or always synchronous? Or can they be “sometimes one, sometimes the other”?](http://stackoverflow.com/q/31944806/1048572) and [What is the intention behind clause 2.2.4 of Promise/A+ spec?](http://stackoverflow.com/q/36932244/1048572) – Bergi Jul 02 '16 at 11:07

1 Answers1

1

Execution is not clear because fs.stat() is async and executes at soonest on next tick, meaning that bar() will always execute before foo().

However, by introducing the if (arg) clause where cb() is executed immediately, then foo() will execute before bar() - this is in sync. Thus, maybeSync() has no predictability without knowing what arg is, before execution.

The definitelyAsync() forces always async execution, by scheduling a call to cb() inside the if (arg) branch, which will always result in bar() being executed before foo() regardless of the arg value.

Mihai Potra
  • 838
  • 4
  • 6