Как поддерживать 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 );
});