On further thought, I'm not so sure.  Consider this code, which creates a
directory if it doesn't already exist and then logs "done".

   return AFS.stat(path).then(stat => {
       if (!stat.isDirectory())
           throw new Error("Path is not a directory.");
   }, error => {
       // Path doesn't exist - create the directory
       return AFS.mkdir(path);
   }).then(val => console.log("done"));

Breaking the error handler out into its own "fail" method seems to make
this awkward to express because the "fail" callback is assigned to the
"then" transform, instead of the original promise as intended.

Conditional branching is as important for method chains as it is
for statement lists. But we do not use conditionals as the basic
statement form:

   if (true) { console.log( 1 ) }
   if (true) { console.log( 2 ) }

One could also argue that promise failure is an exceptional condition,
so two-pronged 'then' encourages API designs that use exceptions for
normal branching - usually not a good sign.

I think arrow functions make the two-arg form considerably more
aesthetically pleasing.

Yes, but is that the only criterion? I'm not sure I can give a better API
on the spot, but there are some things that make me uneasy about
that sample. In particular, a recoverable condition (path doesn't exist)
and an unrecoverable error (path exists, is not a directory) are mixed
into the same channel (promise failure), which leads to the difficulty
you note (disentangling the conditions).

Ok, I had to try anyway;-) It took me a few attempts before I had an alternative that I was willing to show. How about this:

return AFS.stat(path)
   .fail(error => null) // map failure to success condition
   .then(stat =>

       if (!stat)    // Path doesn't exist - create the directory
           return AFS.mkdir(path);
       else if (stat.isDirectory())    // done already
           return 'nothing to do';
       else    // no can do
           throw new Error("Path is not a directory.");

   ).then(val => console.log("done"));

We can then provide a standard promise method for the mapping from success/failure to nullable conditions, such as

   'cond' : cb => this.fail(error => null).then(cb)

and the code would become as pleasing as and the intentions arguably clearer than in the original example.

Claus

_______________________________________________
es-discuss mailing list
[email protected]
https://mail.mozilla.org/listinfo/es-discuss

Reply via email to