Я работаю в проекте, который использует Node.js для Haraka (сервер smtp).
Это Node.JS, и у меня есть небольшая проблема с обратными вызовами. Я не смог преобразовать этот конкретный код для использования обратного вызова.
Итак, это код, который у меня есть:
exports.hook_data = function (next, connection) {
connection.transaction.add_body_filter('', function (content_type, encoding, body_buffer) {
var header = connection.transaction.header.get("header");
if (header == null || header == undefined || header == '') return body_buffer;
var url = 'https://server.com/api?header=' + header ;
var request = require('request');
request.get({ uri: url },
function (err, resp, body) {
var resultFromServer = JSON.parse(body);
return ChangeBuffer(content_type, encoding, body_buffer, resultFromServer);
}
);
});
return next();
}
Этот код не работает, потому что он не ожидает обратного вызова запроса для продолжения. Мне нужно закончить запрос до next()
;
И это требования:
- В конце
exports.hook_data
обязательно вернутьnext()
. Но вернуть его нужно только после запроса. - Мне нужно вернуть
Buffer
вadd_body_filter
, но мне нужно создать буфер с информацией, получаемой с сервера. - Чтобы сделать запрос на получение, мне нужно использовать параметр (
header
), который есть только внутриadd_body_filter
.
Поэтому проблема в том, что я не могу сделать запрос до add_body_filter
и поместить результат в обратный вызов, потому что параметр, который мне нужен для запроса, находится только внутри add_body_filter
.
Какой-нибудь совет, пожалуйста?
4 ответа
Если вы не хотите использовать синхронные блокирующие функции, невозможно выполнить нумерованные требования.
Я изучу причины, лежащие в основе каждого требования, и посмотрю, достигли ли вы своих целей по-другому.
Что касается номинальной стоимости, глядя на код, который у вас есть, я бы искал способ изменить контракт exports.hook_data
, чтобы вы могли вызывать next()
из request.get
Перезвоните.
Изучите руководство Haraka для объекта транзакции и объект заголовка Я не вижу зависимости заголовка от add_body_filter
. Также ваш код не показывает никакой зависимости от add_body_filter
. Итак, ваше третье требование выглядит недействительным.
Учитывая это, я думаю, что следующий псевдокод (поскольку я не могу его протестировать) должен работать для вас.
exports.hook_data = function (next, connection) {
var header = connection.transaction.header.get("header");
if (header == null || header == undefined || header == '') {
return next();
var url = 'https://server.com/api?header=' + header ;
var request = require('request');
request.get({ uri: url },
function (err, resp, body) {
var resultFromServer = JSON.parse(body);
connection.transaction.add_body_filter('', function (content_type, encoding, body_buffer) {
return ChangeBuffer(content_type, encoding, body_buffer, resultFromServer);
});
next();
}
);
}
Если в руководстве Haraka не удалось выделить зависимость заголовка от add_body_filter
и / или вы обнаружили его на основе своего практического опыта, тогда подход Quy, похоже, является подходящим вариантом.
Если вам интересно, когда использовать next () v / s вернуться далее ()
Используйте Async.js или Обещания.
Асинхронная реализация:
exports.hook_data = function (next, connection) {
async.waterfall([
function( done ) {
connection.transaction.add_body_filter('', function( content_type, encoding, body_buffer ) {
var header = connection.transaction.header.get("header");
if ( header == null || header == undefined || header == '' ) {
done(null, body_buffer);
}
done(null, header);
});
},
function( header, done ) {
var url = 'https://server.com/api?header=' + header;
var request = require('request');
request.get({ uri: url },
function( err, resp, body ) {
// do something if there's an error
var resultFromServer = JSON.parse(body);
done(null, ChangeBuffer(content_type, encoding, body_buffer, resultFromServer));
}
);
}
], function( error, buffer ) {
// do something if there's error
next(buffer);
});
}
Здесь много всего, и я рекомендую вам прочитать документы на async.js # waterfall. По сути, он разбивает каждый асинхронный вызов на функциональный блок и ожидает его возврата, прежде чем перейти к следующему блоку.
Опять же, поскольку все они асинхронные, Node отправляет эти задачи в цикл событий ввода-вывода, и об этом позаботятся (неблокирование). Когда этот поток ожидает, он, вероятно, перейдет к следующему запросу, пока этот запрос ожидает.
JavaScript является асинхронным по своей природе. Асинхронное программирование шаблон, который обеспечивает функцию неблокирующего кода, т.е. остановить или не зависеть от другой функции / процесса для выполнения конкретная строка кода. Ссылка: Статья Codementor
Из Википедии
Node.js предоставляет управляемую событиями архитектуру и неблокирующий интерфейс ввода / вывода, разработанный для оптимизации пропускной способности и масштабируемости приложения для веб-приложений в реальном времени.
Что ты можешь сделать?
- Используйте сон / ожидание, т. Е.
setTimeout
(не рекомендуется) - Используйте некоторую асинхронную библиотеку, например https://github.com/caolan/async (рекомендуется)
- Используйте некоторые обещания, например Q
Похожие вопросы
Связанные вопросы
Новые вопросы
javascript
По вопросам программирования на ECMAScript (JavaScript / JS) и его различных диалектах / реализациях (кроме ActionScript). Включите все соответствующие теги в свой вопрос; например, [node.js], [jquery], [json] и т. д.