#javascript #callback
#javascript #обратный вызов
Вопрос:
Я изучаю javascript и переписал этот код из книги:
var controller = {};
controller.queue=[];
controller.add = function (func) {
controller.queue.push(func);
};
controller.run = function () {
controller.queue.shift() (controller.run);
}
function longRunA(callback){
console.log("A");
setTimeout(callback,2000);
}
function longRunB(callback){
console.log("B");
setTimeout(callback,1000);
}
controller.add(longRunA);
controller.add(longRunB);
controller.run();
Распечатка верна, следующие две секунды после B, это то, что он должен был сделать.
Некоторые вещи мне не понятны.
- Почему он пишет
controller.run
в скобках после вызоваcontroller.queue.shift ()
? Я не понимаю, делается ли это для того, чтобы сделать функцию рекурсивной, и я не понимаю роли окружающих круглых скобокcontroller.run
. Консоль сообщает об этой проблеме:uncaught typeerror: controller.queue.shift (..) is not a function at controller.run
controller.add
вызывается сlongRunA
аргументом, но я не понимаю, почему правильно вызыватьlongRunA
функцию без аргументов. Я бы удалил слово обратный вызов в определении функции.
Комментарии:
1. 1. «Метод shift() удаляет первый элемент из массива и возвращает этот удаленный элемент.» , поэтому он возвращает функцию, которую он затем вызывает. 2. Функции являются первоклассными гражданами в javascript. Он не вызывает
longRunA
, он передает функцию в качестве аргумента.
Ответ №1:
Функции в Javascript могут быть:
- передается другим функциям в качестве аргументов
- возвращается изнутри другой функции
- сохраняется внутри структуры данных, такой как массив
- присваивается переменным
Для получения более подробной информации см.: MDN - First-Class Function
Переходя к различным вопросам, которые у вас есть относительно рассматриваемого кода.
почему он пишет controller.run в круглых скобках после вызова controller.queue.shift ()
Если controller.queue.shift()
возвращает функцию, то вы можете вызвать ее, добавив после нее круглые скобки, и, как и в любой другой функции, вы можете передавать ей аргументы. В этом случае controller.run
передается в качестве аргумента функции, возвращаемой controller.queue.shift()
Следующий фрагмент кода показывает пример:
function sayHi(name) {
console.log("Hi " name "!");
}
const arr = [sayHi];
arr.shift()("John");
В приведенном выше фрагменте кода arr.shift()
возвращает sayHi
функцию, которую мы затем вызываем, используя скобки ()
и передавая «John» в качестве аргумента.
Консоль сообщает об этой проблеме: неперехваченная ошибка типа: controller.queue.shift (..) не является функцией в controller.run
Вы получаете эту ошибку, потому что внутри longRunB
функции вы вызываете callback
функцию, т. Е. controller.run
Но когда эта функция вызывается, она пытается получить первый элемент controller.queue
массива, но на данный момент он пуст.
Один из способов решить эту проблему — убедиться, что controller.queue.shift()
это дает вам функцию, прежде чем пытаться ее вызвать.
controller.add вызывается с аргументом longRunA, но я не понимаю, почему правильно вызывать функцию longRunA без аргументов
controller.add
это функция, которая longRunA
передается в качестве аргумента. longRunA
здесь не вызывается.
Ответ №2:
хорошо, благодаря вашим ответам я понимаю ошибку. Последний вызов функции обратного вызова должен быть закомментирован, потому что больше нет функций:
function longRunB (callback) {
console.log ("B");
// setTimeout (callback, 1000);
}
Ответ №3:
для предотвращения ошибки вы можете использовать цикл while.
var controller = {};
controller.queue=[];
controller.add = function (func) {
controller.queue.push(func);
};
controller.run = function () {
while ( controller.queue.length > 0) {
controller.queue.shift()(controller.run);
}
}
function longRunA(callback){
console.log("A");
setTimeout(callback,2000);
}
function longRunB(callback){
console.log("B");
setInterval(callback,1000);
}
controller.add(longRunA);
controller.add(longRunB);
controller.run();
Комментарии:
1. Нет, цикл while не работает для асинхронного упорядочения