Ненужное использование обратного вызова в node.js?
Я изучаю node.js, и я получил большинство основ об асинхронном неблокирующем вводе / выводе. Мой вопрос заключается в том, какой смысл создавать функцию с обратными вызовами, когда сама функция не асинхронна. Даже если созданная вами функция имеет вызов асинхронной функции, я не могу найти причину, по которой вы бы использовали обратный вызов. Я часто вижу это в коде node.js, на который смотрю.
Например, функция, которая отправляет HTTP-запрос и возвращает проанализированный результат запроса:
function withCallback(url, callback) {
request(url, function(err, response, html) {
if (err)
callback(err, null);
callback(null, JSON.parse(html));
});
}
function withoutCallback(url) {
request(url, function(err, response, html) {
if (err)
throw err;
return JSON.parse(html);
});
}
Первая функция с обратным вызовом возвращает результат посредством обратного вызова, в то время как вторая функция просто возвращает его как обычно.
1 ответ
Собирался написать в качестве комментария, но пошел слишком долго.
Вы задаете пару вопросов. Чтобы обратить внимание на правильную точку зрения, которую указывают комментаторы, второй пример просто не будет работать, и, как @Hawkings заявляет более четко, результат не может быть зафиксирован (вашим кодом). Это не сработает, потому что return
во втором примере анонимная функция, которую вы создаете (фактический обратный вызов передается request
) вызывается и возвращает свой результат вглубь request
функция. Кроме того, в вашем примере управление уже вернулось бы к вызывающему withoutCallback
задолго до этого return JSON.parse()
линия вызывается, и как написано, foo = withoutCallback(...)
приведет к foo
быть неопределенным.
Если вы посмотрите на код библиотеки, которая использует обратные вызовы, вы увидите, как они вызываются, и может иметь больше смысла, почему это не сработает. (Хотя я бы посоветовал взглянуть на более простую библиотеку, чем запрос - если вы довольно плохо знакомы с узлом, я думаю, вы найдете библиотеку запросов немного запутанной).
Тем не менее, в случае того, что вы заявляете, ваш вопрос (который не показан в ваших примерах): "Мой вопрос в том, какой смысл создавать функцию с обратными вызовами, когда сама функция не является асинхронной [?]"
В этом конкретном случае нет особого смысла, если а) вы не хотите доказать это в будущем, если он может стать асинхронным из-за дополнительных функций, или б) вы хотите иметь общий интерфейс, в котором другие реализации будут асинхронными. Использовать пример браузера просто потому, что он легко приходит на ум, если вы реализуете универсальное базовое решение для хранения данных, одна реализация которого будет использовать LocalStorage (синхронный), а другие могут использовать IndexedDB или удаленный вызов (оба асинхронные) - Вы все еще хотите написать реализацию LocalStorage с использованием обратных вызовов, чтобы вы могли легко переключаться между реализациями.
Если вам не нравится стиль обратного вызова, подумайте о том, чтобы научиться работать с ним и использовать библиотеки, использующие другие методы или языковые функции для обработки асинхронности, в том числе Promises, Generators или, в соответствующих случаях, EventEmitters. Я лично большой поклонник Обещаний. Сказав это, я бы не советовал ничего из этого, пока вы не разберетесь в том, как и почему колбэки.