javascript-упражнение последовательного обратного вызова

#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, это то, что он должен был сделать.

Некоторые вещи мне не понятны.

  1. Почему он пишет controller.run в скобках после вызова controller.queue.shift () ? Я не понимаю, делается ли это для того, чтобы сделать функцию рекурсивной, и я не понимаю роли окружающих круглых скобок controller.run . Консоль сообщает об этой проблеме: uncaught typeerror: controller.queue.shift (..) is not a function at controller.run
  2. 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 не работает для асинхронного упорядочения