Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Are there differences between .then(functionReference) and .then(function(value){return functionReference(value)})?

Given a named function utilized to handle a Promise value

function handlePromise(data) {
  // do stuff with `data`
  return data
}

a) Passing the named function handlePromise as a reference to .then()

promise.then(handlePromise)

b) Using an anonymous or named function as parameter to .then() and returning the named function handlePromise with Promise value as parameter within the body of the anonymous or named function passed to .then()

promise.then(function /*[functionName]*/(data) {return handlePromise(data)})

Questions

  1. Are there any differences between patterns a) and b)?

  2. If the answer to 1. is yes, what are the differences that should be considered when using either pattern?

like image 782
guest271314 Avatar asked Dec 16 '16 19:12

guest271314


2 Answers

Logic

From a logic perspective there is not anything that would set them apart.

Source

From a source code and style perspective my personal taste is against inline function declarations as they are harder to read (when reading someone else's code, when reading my own its a work of art LOL)

Debugging

From a debugging perspective when the nesting gets deep its is harder to debug when you have a long stack trace of anonymous calls.

Performance

From a performance perspective it is browser dependent. With no significant difference using Firefox. Using Chrome Canary 60 and all versions before. Inline anonymous function declarations are significantly slower after the first call than defined function statements, and function expressions. This is true for both traditional and arrow functions.

Comparing the two alternatives and timing the while loop only

var i,j;
const f = a => a;
j = i = 10000;

while(i--) f(i);  // timed loop


while(j--) (a=>a)(j); // timed loop

The pre defined function is executed 870% quicker than the inline function.

But I have yet to see anyone use promises in performance critical code, the difference in time on the test machine (win10 32bit) is 0.0018µs(*) for f(i) and 0.0157µs for (a=>a)(i)

(*) µs denotes microseconds 1/1,000,000th of a second

Conclusion

The differences are small to insignificant, more a matter of personal taste and style than anything else. If you work in a team use the style outlined in their style guide, if you are project lead or work on your own, use what you are most comfortable with.

The edge case as shown in BenjaminGruenbaum answer I do not consider valid as he explicitly calls f() in then(()=>f()) without an argument. That is the same as const ff = () => f(); delay(0).then(ff) and not a quirk of how the function is defined.

like image 138
Blindman67 Avatar answered Oct 09 '22 21:10

Blindman67


It is possible to create a case where there is a difference when no argument is passed, but it is a stretch and generally you should pass f and not function(x) { return f(x); } or x => f(x) because it is cleaner.

Here is an example causing a difference, the rationale is that functions that takes parameters can cause side effects with those parameters:

function f() {
   if(arguments.length === 0) console.log("win");
   else console.log("Hello World");
}
const delay = ms => new Promise(r => setTimeout(r, ms)); // just a delay
delay(500).then(f); // logs "Hello World";
delay(500).then(() => f()) // logs "win"
like image 25
Benjamin Gruenbaum Avatar answered Oct 09 '22 21:10

Benjamin Gruenbaum