Как правильно определить обратный вызов, который будет выполняться после вызывающей его функции?

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

1. Моя первая попытка:

function doHomeWork (subject, callback) {
    setTimeout(() => {
        console.info(`Started my ${subject} homework`);
    }, 500);
    callback(subject);
}

function finishedHomework (subject) {
    console.info(`Finished my ${subject} homework`);
}

doHomeWork('math', finishedHomework);

Это печатает Finished.. перед Started.., потому что callback(subject) не ждет конца setTimeout.

Если я вызову callback(subject) в setTimeout, он напечатает оба сообщения одновременно, а не то, что я хочу.

Этот отвечать помещает setTimeout в вызов обратного вызова, но в моем гипотетическом случае время потребляет doHomeWork, а не обратный вызов finishedHomeWork, поэтому он недействителен для этого примера.

2. Моя вторая попытка:

function homeWork (subject, callback) {
    doHomeWork(subject);
    callback(subject);
}

function doHomeWork (subject) {
    setTimeout(() => {
        console.info(`Started my ${subject} homework`);
    }, 500);
}

function finishedHomework (subject) {
    console.info(`Finished my ${subject} homework`);
}

homeWork('math', finishedHomework);

Это также печатает Finished.. перед Started.., потому что callback(subject) не ждет doHomeWork(subject).

Итак, объяснение обратного вызова говорит, что это функция, которая будет выполняться после вызывающей ее функции, не так ли? Но, как показали мои примеры, я не нашел способа определить его запуск после финиша doHomeWork.

Чего не хватает?

На самом деле вы не вызываете обратный вызов внутри setTimeout сразу после того, как он запланирован. Просто назвать его обратным вызовом не получится волшебным образом вызвать его в нужное время!

jonrsharpe 23.05.2019 17:37
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
В настоящее время производительность загрузки веб-сайта имеет решающее значение не только для удобства пользователей, но и для ранжирования в...
Безумие обратных вызовов в javascript [JS]
Безумие обратных вызовов в javascript [JS]
Здравствуйте! Юный падаван 🚀. Присоединяйся ко мне, чтобы разобраться в одной из самых запутанных концепций, когда вы начинаете изучать мир...
Система управления парковками с использованием HTML, CSS и JavaScript
Система управления парковками с использованием HTML, CSS и JavaScript
Веб-сайт по управлению парковками был создан с использованием HTML, CSS и JavaScript. Это простой сайт, ничего вычурного. Основная цель -...
JavaScript Вопросы с множественным выбором и ответы
JavaScript Вопросы с множественным выбором и ответы
Если вы ищете платформу, которая предоставляет вам бесплатный тест JavaScript MCQ (Multiple Choice Questions With Answers) для оценки ваших знаний,...
3
1
43
3
Перейти к ответу Данный вопрос помечен как решенный

Ответы 3

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

homeWork('math', function(){finishedHomework()});

Зачем вам это делать, а не просто передача функции? Какая разница?

jonrsharpe 23.05.2019 17:35

Привет, проблема в том, что когда это функция

() => {console.info(`Started my ${subject} homework`);}

запускается только тогда, когда setTimeout заканчивается, поэтому лучшее решение, которое я вижу, это

function doHomeWork (subject, callback) {
    console.info(`Started my ${subject} homework`);
    setTimeout(() => {
        callback(subject);
    }, 500);
}

Я писал об этом в вопросе, это похоже на то, что готовая домашняя работа требует времени, но я имитирую, что выполнение домашней работы требует некоторого времени.

Aldo 23.05.2019 18:06
Ответ принят как подходящий

Во-первых, вот почему вам нужны обещания.

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

Чтобы сделать это только с обратными вызовами, поместите свой обратный вызов в функцию setTimeout.

function doHomeWork (subject, callback) {
    setTimeout(() => {
        console.info(`Started my ${subject} homework`);
        callback(subject); // <---------   CHANGE MADE HERE
    }, 500);
    //callback(subject)  // Remove this line, and move it up ^^^
}

function finishedHomework (subject) {
    console.info(`Finished my ${subject} homework`);
}

doHomeWork('math', finishedHomework);

Однако, вы должны просто использовать промисы. Они на самом деле просты и гораздо более читабельны. Эту же функцию можно записать так:

function doHomeWork (subject) {
  return new Promise( (resolve,reject) => {   //Turns a regular funciton into a promise
    setTimeout(() => {
        console.info(`Started my ${subject} homework`);
        resolve(subject);
    }, 500);
  }); 
}

function finishedHomework (subject) {
    console.info(`Finished my ${subject} homework`);
}

doHomeWork('math').then( (subject) => { //since doHomeWork returns a promise we can use .then() on it
    finishedHomework(subject);
});

Я где-то видел, что обратный вызов будет выполняться в конце вызывающей функции. Оказывается, это неправильный способ объяснить обратные вызовы. То, что вы только что написали, - это то, что я ожидал увидеть: Javascript все равно.

Aldo 23.05.2019 18:43

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

Badrush 23.05.2019 19:07

Но я бы сказал, никогда не предполагайте, что javascript будет ждать завершения функции. Если что-то займет незначительное количество времени, например HTTP-запросы, обработка больших данных или что-то, что связано со временем (setTimeout), вам следует обратить внимание на то, чтобы превратить функцию в обещание, чтобы вы могли быть уверены, что все будет работать в правильном порядке.

Badrush 23.05.2019 19:09

Другие вопросы по теме