Как вы можете использовать обратный вызов, чтобы гарантировать последовательное выполнение? - PullRequest
0 голосов
/ 14 января 2020

Я пытаюсь обернуться вокруг обратных вызовов, и я не понимаю, как обратные вызовы гарантируют , что оператор выполнится через (в терминах времени) другого оператора, который принимает неизвестно количество времени. Меня не волнуют обещаний, ожидающих, asyn c и т. Д. c, но только простые обратные вызовы, которые я пытаюсь выучить.


Например, мой метод ниже выполнит обратный вызов до наступления неизвестного времени. Я вижу, как обратные вызовы могут использоваться для выполнения чего-либо , потому что произошло событие, но не , как они могут быть использованы для гарантии того, что что-то будет выполнено после (с точки зрения времени) что-то еще завершилось и вернуло что-то значимое.

function foo(callback) {
    setTimeout(() => console.log("Do something with unknown time"),
        2000);
    callback();
}

function callback() {
    console.log("Execute callback");
}

foo(callback);

Итак, что я спрашиваю, могут ли обратные вызовы использоваться для гарантии последовательности выполнения во временной области? Или их единственная цель - реагировать на события?

Ответы [ 3 ]

1 голос
/ 14 января 2020

Обратные вызовы - это способ вызова функции, которая передается в качестве параметра функции invoker (в вашем примере foo). Обратные вызовы гарантируют, что функция будет вызвана, если не произойдет ошибки до ее вызова внутри функции. Обратные вызовы тоже не асинхронные, но способ, которым он выполняется позже внутри функции после некоторой строки кода, заставляет всех сначала думать, что она асинхронна.

И, как вы добавили функцию setTimeout в приведенном выше примере, setTimeout - это функция асинхронного обратного вызова, которая вызывает его обратный вызов (в вашем коде () => console.log("Do something with unknown time")) асинхронно по истечении определенного времени (2000). Таким образом, setTimeout не остановит выполнение на 2 секунды, как вы ожидали, вместо этого он позволит выполнить дальнейшую строку кода, не беспокоясь о том, что произойдет внутри его обратного вызова. Таким образом, callback() сработает в тот момент, когда сработает foo(callback);.

Более подробную информацию о обратном вызове можно найти здесь.

1 голос
/ 14 января 2020

Вы задали два вопроса,

  1. Гарантируется ли последовательность выполнения обратного вызова?

  2. Отвечает ли обратный вызов только на события?

Ответ

  1. Да.

Насколько я понимаю, callback просто вызывает другую функцию, которая должна быть запущена сейчас (когда она вызывается)

Это гарантия запуска сразу после вызова ,

Чтобы убедиться, что что-то вызывается до того, как будет выполнен обратный вызов, просто поместите вещи, которые вы хотите вызвать, в первую очередь, прежде чем будет выполнен обратный вызов.

Например, из вашего кода, немного изменив его, обратный вызов гарантированно будет запущен после выполнения console.log.

function foo(callback) {
    setTimeout(() => {
        console.log("Do something with unknown time");
        callback();
    }, 2000);
}

function callback() {
    console.log("Execute callback");
}

foo(callback);

Это setTimeout, который откладывает выполнение и не связан с методологией обратного вызова.

Конечно, обратный вызов может использоваться в качестве обратного вызова для ответа на событие, как и elem.addEventListener("click", callback);. Но не только это.

Простой пример будет проиллюстрирован ниже.

Например,

var map = function(arr, callback) {
  var result = [];
  for (var i = 0, len = arr.length; i < len; i++) {
    result.push(callback(arr[i]));
  }
  return result;
};

map([0, 1, 2, 3], function(item) {
  return item * 2;
})

Отредактировано

Это изменение относится к

Например, если я делаю вызов из базы данных, я не знаю, сколько времени потребуется для извлечения данных. Если я попытаюсь получить к нему доступ до того, как он прибудет, я получу ошибку.

Вызов базы данных ни в коем случае не отличается от асинхронного c http-запроса. Итак, здесь я буду использовать XMLHttpRequest, чтобы продемонстрировать, как использовать обратный вызов для обеспечения этого. Но обычно это функции, предоставляемые в браузере или уже node.js. Так что вам не нужно писать это самостоятельно. Конечно, чтобы предотвратить обратный вызов, я лично предпочитаю использовать Promise или async/await. Но это немного из топи c.

Итак, давайте посмотрим, как XMLHttpRequest может использовать обратный вызов для обработки асинхронной c задачи.

var sendRequest = function(callback) {
  var xhttp = new XMLHttpRequest();
  xhttp.onreadystatechange = function() {
    if (this.readyState == 4 && this.status == 200) {
       callback(this); 
    }
  };
  xhttp.open("GET", "filename", true);
  xhttp.send();
}

и вы можете использовать обратный вызов для обработки асин c события. Иногда вы не знаете, когда это произойдет. И основная идея о том, как это работает, основана на примере, который я сказал в ответе 1.

0 голосов
/ 14 января 2020

Если я понимаю, что вы имеете в виду правильно, вы можете использовать обратный вызов как событие, чтобы сделать что-то, например: onerror, oncomplete ...

В этом примере мы начинаем работать todo функция, и у нас есть oncomplete функция, которую можно использовать в качестве обратного вызова для выполнения каких-либо действий после завершения работы с todo функцией.

Во время работы, если есть какая-либо ошибка, она будет зарегистрирована в onerror функция.

function todo(oncomplete, onerror) {
    try {
        console.log("Start...");

        console.log("Do something with unknown time");

        setTimeout(() => oncomplete(),2000);
        
        // you can try to throw error here to test
        // throw new Error("Some error message...");
    } catch (e) {
        onerror(e);
    }
}

function oncomplete() {
    console.log("Done!");
}

function onerror(e) {
    console.error(e.message);
}

todo(oncomplete, onerror);
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...