Aminadav February 2016

How to support 2 types of callback in Javascript

In the intercom-client github I see this code:

client.users.list(function (d) {
  // d is the response from the server
});

// Or

client.users.list(function (err, d) {
  // err is an error response object, or null
  // d is a successful response object, or null
});

My question is: How intercom know if I pass funcrtion(err,d) or just function(data).

I check the source code and found that they use bluebird library. How bluebird does it?

I want that my function will do the same.

In other words:

function myFunction(data,callback){
  if (callbackListenToErrArgument(callback)) 
       callback(null,data)
   else
       callback(data)

}

How to implement callbackListenToErrArgument function?

Answers


Madara Uchiha February 2016

One can inspect the .length property on the function getting passed. The .length property is the number of arguments defined for the function.

function hasErrorArgument(callback) {
  if (callback.length < 2) { return false; } // Has 1 or 0.
  else return true; // has 2 or more
} // Yes, I know it can be reduced to one line. Sue me.

Please note: This is bad practice. You should provide a uniform signature to the callbacks you accept. (err, data) => {} is a good signature to follow.

Or even better, have your list() function return a Promise object: (Promises are natively supported only in some browsers. Check compatibility before use, or use a polyfill or a library).

client.users.list()
  .then(listOfUsers => {
    // Use data here
  })
  .catch(err => {
    // Handle errors here
  });


loretoparisi February 2016

Assumed that looking at the method length:

fun=function(a,b,c) {
  console.log(a,b,c)
}
(a,b,c) {
  console.log(a,b,c)
}
fun.prototype.constructor.length
3

could be considered a bad practice, as stated by @madara-uchiha, the bluebird library has a method caller function that is:

var makeMethodCaller = function (methodName) {
    return new Function("ensureMethod", "                                    \n\
        return function(obj) {                                               \n\
            'use strict'                                                     \n\
            var len = this.length;                                           \n\
            ensureMethod(obj, 'methodName');                                 \n\
            switch(len) {                                                    \n\
                case 1: return obj.methodName(this[0]);                      \n\
                case 2: return obj.methodName(this[0], this[1]);             \n\
                case 3: return obj.methodName(this[0], this[1], this[2]);    \n\
                case 0: return obj.methodName();                             \n\
                default:                                                     \n\
                    return obj.methodName.apply(obj, this);                  \n\
            }                                                                \n\
        };                                                                   \n\
        ".replace(/methodName/g, methodName))(ensureMethod);
};

[UPDATE] I have added a working snippet of the Bluebird code to discuss it. As someone stated this seems to be applied to something else, even if there is a method length guard in the switch case. Check the code:

var c 

Post Status

Asked in February 2016
Viewed 1,702 times
Voted 7
Answered 2 times

Search




Leave an answer