Я только начал использовать узел, и одну вещь, которую я быстро заметил, это то, как быстро обратные вызовы могут вырасти до глупого уровня отступа:
doStuff(arg1, arg2, function(err, result) {
doMoreStuff(arg3, arg4, function(err, result) {
doEvenMoreStuff(arg5, arg6, function(err, result) {
omgHowDidIGetHere();
});
});
});
Официальный стиль говорит поместить каждый обратный вызов в отдельной функции, но кажется , что чрезмерно ограничительным на использовании замыканий, и делает один объект объявлен на уровне верхнего доступны несколько уровней вниз, как объект должен быть передан через все промежуточные обратные вызовы.
Можно ли использовать область действия, чтобы помочь здесь? Поместить все функции обратного вызова, которым нужен доступ к объекту global-ish, в функцию, которая объявляет этот объект, чтобы он перешел в замыкание?
function topLevelFunction(globalishObject, callback) {
function doMoreStuffImpl(err, result) {
doMoreStuff(arg5, arg6, function(err, result) {
callback(null, globalishObject);
});
}
doStuff(arg1, arg2, doMoreStuffImpl);
}
и так далее для еще нескольких слоев ...
Или существуют платформы и т. Д., Чтобы помочь уменьшить уровни отступов, не объявляя именованную функцию для каждого обратного вызова? Как вы справляетесь с пирамидой обратного вызова?
источник
Ответы:
Существует несколько реализаций «обещаний»:
Например, вы можете переписать это вложенные обратные вызовы
подобно
Вместо обратного вызова в обратном вызове
a(b(c()))
вы связываете «.then»a().then(b()).then(c())
.Введение здесь: http://howtonode.org/promises
источник
В качестве альтернативы обещаниям вы должны взглянуть на
yield
ключевое слово в сочетании с функциями генератора, которые будут представлены в EcmaScript 6. Оба они доступны сегодня в сборках Node.js 0.11.x, но требуют, чтобы вы дополнительно указывали--harmony
флаг при запуске Node .js:Использование этих конструкций и библиотеки, такой как TJ Holowaychuk's co, позволяет вам писать асинхронный код в стиле, который выглядит как синхронный код, хотя он все еще выполняется асинхронным способом. По сути, эти вещи вместе реализуют совместную поддержку Node.js.
По сути, вам нужно написать функцию генератора для кода, который выполняет асинхронные операции, вызвать там асинхронные операции, но поставить перед ними
yield
ключевое слово. Итак, в конце ваш код выглядит так:Для запуска этой функции генератора вам нужна библиотека, такая как ранее упомянутая co. Звонок выглядит так:
Или, чтобы поместить это в линию:
Обратите внимание, что из функций генератора вы можете вызывать другие функции генератора, все, что вам нужно сделать, это
yield
снова поставить перед ними префикс .Чтобы ознакомиться с этой темой, поищите в Google такие термины, как
yield generators es6 async nodejs
и вы должны найти тонны информации. Требуется некоторое время, чтобы привыкнуть к этому, но как только вы это получите, вы не захотите возвращаться никогда.Обратите внимание, что это не только обеспечивает более приятный синтаксис для вызова функций, но также позволяет использовать обычные (синхронные) элементы логики потока управления, такие как
for
циклы илиtry
/catch
. Больше не нужно возиться с множеством обратных вызовов и всем этим.Удачи и приятного времяпровождения :-)!
источник
Теперь у вас есть пакет asyncawait , с очень близкого синтаксиса к тому , что должно быть будущее нативная поддержка из
await
&async
в узле.По сути, это позволяет писать асинхронный код, выглядящий синхронно , резко снижая LOC и уровни отступов, с компромиссом небольшого снижения производительности (числа владельцев пакетов на 79% быстрее по сравнению с необработанными обратными вызовами), которые, как мы надеемся, будут уменьшены, когда будет доступна собственная поддержка.
Тем не менее, это хороший выбор, чтобы выбраться из ада обратного вызова / пирамиды обреченного кошмара IMO, когда производительность не является первостепенной задачей, и где стиль синхронной записи лучше соответствует потребностям вашего проекта.
Базовый пример из пакета документов:
источник