如何进行需要其子函数信息的回调
How can I make a callback that requires info of its child function
我在一个项目中工作,该项目使用 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
是强制性的returnnext()
。但是它只需要return请求之后就可以了。
- 我需要 return 在
add_body_filter
中创建 Buffer
,但我需要使用从服务器获取的信息创建缓冲区。
- 为了发出 Get 请求,我需要使用一个参数 (
header
),我只在 add_body_filter
.
所以问题是我无法在 add_body_filter
之前发出请求并将结果放入回调中,因为我发出请求所需的参数仅在 add_body_filter
中。
有什么建议吗?
除非你愿意使用同步、阻塞的函数,否则是不可能满足你编号的要求的。
我会检查每个要求背后的原因,看看您是否以不同的方式实现了目标。
从表面上看,只看你那里的代码,我会寻找一种方法来改变 exports.hook_data
的合同,这样你就可以从内部调用 next()
request.get
回调。
使用 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 上的文档。本质上,它将每个异步调用分解到它的功能块上,并等待它到 return,然后再继续到下一个块。
同样,由于这些都是异步的,Node 将这些任务提交给 IO 事件循环,并在那里处理(非阻塞)。当此线程正在等待时,它可能会在等待此请求时继续执行下一个请求。
查看 Transaction object & Header object 的 Haraka 手册,我没有看到 Header 对 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 手册未能突出显示 Header 对 add_body_filter
的依赖和/或您根据自己的实践经验发现了它,那么 Quy 的方法似乎是可行的方法。
如果您想知道 when to use next() v/s return next()
我使用 Q
来处理您代码的每个部分的优先级,您可以通过几个步骤使用它:
npm install q
.
var request = require('request');
var Q = require('q');
exports.hook_data = function () {
var url, header;
Q()
.then(function(){
connection.transaction.add_body_filter('', function(content_type, encoding, body_buffer) {
header = connection.transaction.header.get("header");
if (header == null || header == undefined || header == ''){return body_buffer;}
url = 'https://server.com/api?header=' + header ;
})
.then(function(){
request.get({ uri: url }, function (err, resp, body) {
var resultFromServer = JSON.parse(body);
return ChangeBuffer(content_type,encoding,body_buffer,resultFromServer);
});
})
}
在async
场景下,使用q
回调比我认为的其他方式更好。
JavaScript is asynchronous in nature. Asynchronous is a programming
pattern which provides the feature of non-blocking code i.e do not
stop or do not depend on another function / process to execute a
particular line of code.
Ref: Codementor Article
来自维基百科
Node.js provides an event-driven architecture and a non-blocking I/O API designed to optimize an application's throughput and scalability for real-time web applications
你能做什么?
- 使用 sleep/wait 即
setTimeout
(不推荐)
- 使用一些异步库,例如 https://github.com/caolan/async(推荐)
- 使用像 Q
这样的承诺库
我在一个项目中工作,该项目使用 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
是强制性的returnnext()
。但是它只需要return请求之后就可以了。 - 我需要 return 在
add_body_filter
中创建Buffer
,但我需要使用从服务器获取的信息创建缓冲区。 - 为了发出 Get 请求,我需要使用一个参数 (
header
),我只在add_body_filter
.
所以问题是我无法在 add_body_filter
之前发出请求并将结果放入回调中,因为我发出请求所需的参数仅在 add_body_filter
中。
有什么建议吗?
除非你愿意使用同步、阻塞的函数,否则是不可能满足你编号的要求的。
我会检查每个要求背后的原因,看看您是否以不同的方式实现了目标。
从表面上看,只看你那里的代码,我会寻找一种方法来改变 exports.hook_data
的合同,这样你就可以从内部调用 next()
request.get
回调。
使用 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 上的文档。本质上,它将每个异步调用分解到它的功能块上,并等待它到 return,然后再继续到下一个块。
同样,由于这些都是异步的,Node 将这些任务提交给 IO 事件循环,并在那里处理(非阻塞)。当此线程正在等待时,它可能会在等待此请求时继续执行下一个请求。
查看 Transaction object & Header object 的 Haraka 手册,我没有看到 Header 对 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 手册未能突出显示 Header 对 add_body_filter
的依赖和/或您根据自己的实践经验发现了它,那么 Quy 的方法似乎是可行的方法。
如果您想知道 when to use next() v/s return next()
我使用 Q
来处理您代码的每个部分的优先级,您可以通过几个步骤使用它:
npm install q
.var request = require('request'); var Q = require('q'); exports.hook_data = function () { var url, header; Q() .then(function(){ connection.transaction.add_body_filter('', function(content_type, encoding, body_buffer) { header = connection.transaction.header.get("header"); if (header == null || header == undefined || header == ''){return body_buffer;} url = 'https://server.com/api?header=' + header ; }) .then(function(){ request.get({ uri: url }, function (err, resp, body) { var resultFromServer = JSON.parse(body); return ChangeBuffer(content_type,encoding,body_buffer,resultFromServer); }); }) }
在async
场景下,使用q
回调比我认为的其他方式更好。
JavaScript is asynchronous in nature. Asynchronous is a programming pattern which provides the feature of non-blocking code i.e do not stop or do not depend on another function / process to execute a particular line of code. Ref: Codementor Article
来自维基百科
Node.js provides an event-driven architecture and a non-blocking I/O API designed to optimize an application's throughput and scalability for real-time web applications
你能做什么?
- 使用 sleep/wait 即
setTimeout
(不推荐) - 使用一些异步库,例如 https://github.com/caolan/async(推荐)
- 使用像 Q 这样的承诺库