Как поддерживать 2 типа обратного вызова в Javascript

В intercom-client github я вижу этот код:

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
});

Мой вопрос: как intercom знать, если я пройду funcrtion(err,d) или просто function(data),

Я проверил исходный код и обнаружил, что они используют bluebird библиотека. Как блюберд это делает?

Я хочу, чтобы моя функция делала то же самое.

Другими словами:

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

}

Как реализовать callbackListenToErrArgument функционировать?

2 ответа

Решение

Можно осмотреть .length свойство переданной функции. .length Свойство - это число аргументов, определенных для функции.

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.

Пожалуйста, обратите внимание: это плохая практика. Вы должны предоставить единую подпись для обратных вызовов, которые вы принимаете. (err, data) => {} хорошая подпись для подражания

Или даже лучше, есть ваш list() функция возвращает Promise object: (Обещания изначально поддерживаются только в некоторых браузерах. Проверьте совместимость перед использованием или используйте полифилл или библиотеку).

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

Предполагается, что, глядя на длину метода:

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

@ Madara-Uchiha, bluebird В библиотеке есть функция вызова метода:

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);
};

[ОБНОВЛЕНИЕ] Я добавил рабочий фрагмент кода Bluebird, чтобы обсудить это. Как кто-то сказал, это, кажется, применимо к чему-то другому, даже если в случае коммутатора есть защита длины метода. Проверьте код:

var console={}
console.log=function(msgs) { document.writeln(msgs)};

var makeMethodCaller = function (methodName) {
    return new Function("ensureMethod", "                                    \n\
        return function(obj) {                                               \n\
            var len = this.length;                                           \n\
            console.log(\"Who is this\"+this);                                           \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);
};
function ensureMethod(obj, methodName) {
    var fn;
    if (obj != null) fn = obj[methodName];
    if (typeof fn !== "function") {
        var message = "Object " + JSON.stringify(obj) + " has no method '" +
            JSON.stringify(methodName) + "'";
        throw new Error(message);
    }
    return fn;
}
var fn=makeMethodCaller("callMe");


console.log(fn)

var obj0= {
 callMe : function() { console.log("\n\n\ncalled with 0 params")}
};
var obj1= {
 callMe : function(a) { console.log("\n\n\ncalled with 1 params")}
};
var obj2= {
 callMe : function(a,b) { console.log("\n\n\ncalled 2 params")}
};
var obj3= {
 callMe : function(a,b,c) { console.log("\n\n\ncalled 3 params")}
};


[obj0,obj1,obj2,obj3].map(function(e) { 
  return fn( e );
});

Другие вопросы по тегам