Что касается решения проблемы, у меня есть полностью работающее решение, которое я только что закончил здесь:
// synchronous dynamic script loading.
// takes an array of js url's to be loaded in that specific order.
// assembles an array of functions that are referenced more directly rather than
// using only nested closures. I couldn't get it going with the closures and gave up on it.
function js_load(resources, cb_done) {
var cb_list = []; // this is not space optimal but nobody gives a damn
array_each(resources, function(r, i) {
cb_list[i] = function() {
var x = document.body.appendChild(document.createElement('script'));
x.src = r;
console.log("loading "+r);
x.onload = function() {
console.log("js_load: loaded "+r);
if (i === resources.length-1) {
cb_done();
} else {
cb_list[i+1]();
}
};
};
});
cb_list[0]();
}
Я полностью доволен этим, потому что теперь он делает то, что я хочу, и, вероятно, его гораздо проще отлаживать, чем мой первый подход, если бы он был успешным.
Но чего я не могу понять, так это того, почему я никогда не мог заставить его работать.
Это выглядело примерно так.
function js_load(resources, cb_done) {
var cur_cont = cb_done;
// So this is an iterative approach that makes a nested "function stack" where
// the inner functions are hidden inside the closures.
array_each_reverse(resources, function(r) {
// the stack of callbacks must be assembled in reverse order
var tmp_f = function() {
var x = document.body.appendChild(document.createElement('script'));
x.src = r;
console.log("loading "+r);
x.onload = function() { console.log("js_load: loaded "+r); cur_cont(); }; // TODO: get rid of this function creation once we know it works right
};
cur_cont = tmp_f; // Trying here to not make the function recursive. We're generating a closure with it inside. Doesn't seem to have worked :(
});
cur_cont();
}
Он продолжал пытаться вызвать себя в бесконечном цикле, помимо других странных вещей, и во время отладки очень сложно определить, что это за функция и что она содержит.
Я не копался в коде, но похоже, что jQuery.queue
также реализовал механизм, аналогичный моему рабочему (используя массив для отслеживания очереди продолжений), а не используя только замыкания.
Мой вопрос таков: возможно ли создать функцию Javascript, которая может принимать функцию в качестве аргумента и дополнять ее списком других функций, создавая замыкания, которые обертывают функции, которые она создает сама?
Это действительно трудно описать. Но я уверен, что у кого-то есть подходящий математический термин, подкрепленный теорией.
P.S. В приведенном выше коде на эти подпрограммы ссылаются
// iterates through array (which as you know is a hash), via a for loop over integers
// f receives args (value, index)
function array_each(arr, f) {
var l = arr.length; // will die if you modify the array in the loop function. BEWARE
for (var i=0; i<l; ++i) {
f(arr[i], i);
}
}
function array_each_reverse(arr, f) {
var l = arr.length; // will die if you modify the array in the loop function. BEWARE
for (var i=l-1; i>=0; --i) {
f(arr[i], i);
}
}
[1, 2, 3].forEach
. - person Eric   schedule 25.03.2013cur_cont
. Когда обработчики выполняются, все они используют последнее значениеcur_cont
. - person Eric   schedule 25.03.2013