Например, я хотел бы определить обратный вызов, который показывает сообщение о завершении задачи только с помощью обратных вызовов. Пожалуйста, не говорите об обещаниях, я знаю, что это может быть применено здесь.
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.
Чего не хватает?



![Безумие обратных вызовов в javascript [JS]](https://i.imgur.com/WsjO6zJb.png)


Может быть, попробовать обернуть свой обратный вызов в анонимную функцию? (Не проверено, но обычно это мое первое предположение, когда у меня возникает та же проблема, с которой вы имеете дело.)
homeWork('math', function(){finishedHomework()});
Зачем вам это делать, а не просто передача функции? Какая разница?
Привет, проблема в том, что когда это функция
() => {console.info(`Started my ${subject} homework`);}
запускается только тогда, когда setTimeout заканчивается, поэтому лучшее решение, которое я вижу, это
function doHomeWork (subject, callback) {
console.info(`Started my ${subject} homework`);
setTimeout(() => {
callback(subject);
}, 500);
}
Я писал об этом в вопросе, это похоже на то, что готовая домашняя работа требует времени, но я имитирую, что выполнение домашней работы требует некоторого времени.
Во-первых, вот почему вам нужны обещания.
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 все равно.
Возможно, вы думаете о библиотеках, которые создали функции, которые принимают обратные вызовы для вас, обычно они могут принимать обратные вызовы, но чего вы не видите, так это того, что они гарантируют, что обратные вызовы запускаются только после завершения исходной функции, а не как просто, просто вызывая его внутри родительской функции.
Но я бы сказал, никогда не предполагайте, что javascript будет ждать завершения функции. Если что-то займет незначительное количество времени, например HTTP-запросы, обработка больших данных или что-то, что связано со временем (setTimeout), вам следует обратить внимание на то, чтобы превратить функцию в обещание, чтобы вы могли быть уверены, что все будет работать в правильном порядке.
На самом деле вы не вызываете обратный вызов внутри setTimeout сразу после того, как он запланирован. Просто назвать его обратным вызовом не получится волшебным образом вызвать его в нужное время!