Если вы не хотите сериализовать AJAX, у меня нет другого способа сделать то, что вы предлагаете. Тем не менее, я думаю, что то, что у вас есть, довольно хорошо, но вы можете немного очистить структуру, чтобы не засорять объект, который вы создаете, данными инициализации.
Вот функция, которая может вам помочь:
function gate(fn, number_of_calls_before_opening) {
return function() {
arguments.callee._call_count = (arguments.callee._call_count || 0) + 1;
if (arguments.callee._call_count >= number_of_calls_before_opening)
fn.apply(null, arguments);
};
}
Эта функция называется функцией высшего порядка - функцией, принимающей функции в качестве аргументов. Эта конкретная функция возвращает функцию, которая вызывает переданную функцию, когда она была вызвана number_of_calls_before_opening
раз. Например:
var f = gate(function(arg) { alert(arg); }, 2);
f('hello');
f('world'); // An alert will popup for this call.
Вы можете использовать это как метод обратного вызова:
foo.bar = function() {
var callback = gate(this.method, 2);
sendAjax(new Request(), callback);
sendAjax(new Request(), callback);
}
Второй обратный вызов, в зависимости от того, что будет, вызовет method
. Но это приводит к другой проблеме: функция gate
вызывает переданную функцию без какого-либо контекста, то есть this
будет ссылаться на глобальный объект, а не на объект, который вы создаете. Есть несколько способов обойти это: вы можете закрыть this
, присвоив ему псевдоним me
или self
. Или вы можете создать другую функцию более высокого порядка, которая сделает именно это.
Вот как будет выглядеть первый случай:
foo.bar = function() {
var me = this;
var callback = gate(function(a,b,c) { me.method(a,b,c); }, 2);
sendAjax(new Request(), callback);
sendAjax(new Request(), callback);
}
В последнем случае другая функция более высокого порядка будет выглядеть примерно так:
function bind_context(context, fn) {
return function() {
return fn.apply(context, arguments);
};
}
Эта функция возвращает функцию, которая вызывает переданную функцию в переданном контексте. Пример этого может быть следующим:
var obj = {};
var func = function(name) { this.name = name; };
var method = bind_context(obj, func);
method('Your Name!');
alert(obj.name); // Your Name!
Чтобы представить это в перспективе, ваш код будет выглядеть следующим образом:
foo.bar = function() {
var callback = gate(bind_context(this, this.method), 2);
sendAjax(new Request(), callback);
sendAjax(new Request(), callback);
}
В любом случае, сделав эти рефакторинги, вы очистите строящийся объект от всех его членов, которые необходимы только для инициализации.