在 Meteor 1.3 中使用 Request npm 模块同步
using Request npm module synchronous in Meteor 1.3
我尝试在 Meteor 1.3.2.4 中使用 request npm package 作为同步。
基于this Meteor guide article,首先我尝试像下面这样使用Meteor.bindEnvironment
:
import request from 'request';
let result = {success: false, error: null, content: ""};
let requestOptions = {
url: <MY-URL-HERE>
};
request(requestOptions, Meteor.bindEnvironment((error, response, html) => {
if (!error && response.statusCode == 200) {
result.success = true;
result.content = html;
result.error = null;
}
else {
result.success = false;
result.content = "";
result.error = error;
}
}));
不过好像还是异步调用。
下一步我尝试在流星论坛上使用基于this answer的Meteor.wrapAsync
,这是下一个尝试代码:
import request from 'request';
let result = {success: false, error: null, content: ""};
let requestOptions = {
url: <MY-URL-HERE>
};
let func = function (options, callback) {
request(options, function (error, response, body) {
console.log("error: " + JSON.stringify(error));
console.log("response: " + JSON.stringify(response));
console.log("body: " + JSON.stringify(body));
callback(error, {response, body});
});
};
let {error, response, body} = syncRequest(requestOptions);
console.log("error2: " + JSON.stringify(error));
console.log("response2: " + JSON.stringify(response));
console.log("body2: " + JSON.stringify(body));
if (response.statusCode == 200) {
result.success = true;
result.content = body;
result.error = null;
}
else {
result.success = false;
result.content = "";
result.error = error;
}
此代码工作正常,但请求包含错误。当请求包含错误时(例如 url 不正确),此中断会出现以下异常:
I20160518-08:24:22.180(4.5)? error: {}
I20160518-08:24:22.181(4.5)? response: undefined
I20160518-08:24:22.182(4.5)? body: undefined
W20160518-08:24:22.839(4.5)? (STDERR) TypeError: The header content contains invalid characters
W20160518-08:24:22.839(4.5)? (STDERR) at Object.Future.wait (/home/cyc/.meteor/packages/meteor-tool/.1.3.2_4.7bk6xv++os.linux.x86_64+web.browser+web.cordova/mt-os.linux.x86_64/dev_bundle/server-lib/node_modules/fibers/future.js:420:15)
W20160518-08:24:22.839(4.5)? (STDERR) at packages/meteor/helpers.js:119:1
W20160518-08:24:22.839(4.5)? (STDERR) at Object.getContent (server/lib/get_content.js:51:26)
W20160518-08:24:22.839(4.5)? (STDERR) at Object.fetch (server/lib/get_content.js:205:27)
W20160518-08:24:22.839(4.5)? (STDERR) at Object.fetchSource (server/lib/get_content.js:369:31)
W20160518-08:24:22.840(4.5)? (STDERR) at [object Object].action (server/controller/postsController.js:79:39)
W20160518-08:24:22.840(4.5)? (STDERR) at [object Object].handle (packages/iron_middleware-stack/lib/handler.js:74:1)
W20160518-08:24:22.840(4.5)? (STDERR) at boundNext (packages/iron_middleware-stack/lib/middleware_stack.js:251:1)
W20160518-08:24:22.840(4.5)? (STDERR) at runWithEnvironment (packages/meteor/dynamics_nodejs.js:110:1)
W20160518-08:24:22.840(4.5)? (STDERR) at packages/meteor/dynamics_nodejs.js:123:1
W20160518-08:24:22.840(4.5)? (STDERR) - - - - -
W20160518-08:24:22.840(4.5)? (STDERR) at ClientRequest.OutgoingMessage.setHeader (http.js:733:13)
W20160518-08:24:22.840(4.5)? (STDERR) at new ClientRequest (http.js:1429:14)
W20160518-08:24:22.840(4.5)? (STDERR) at Object.exports.request (http.js:1899:10)
W20160518-08:24:22.841(4.5)? (STDERR) at Request.start (/home/cyc/Programming/Projects/content/Sources/node_modules/request/request.js:753:32)
W20160518-08:24:22.841(4.5)? (STDERR) at Request.end (/home/cyc/Programming/Projects/content/Sources/node_modules/request/request.js:1418:10)
W20160518-08:24:22.841(4.5)? (STDERR) at end (/home/cyc/Programming/Projects/content/Sources/node_modules/request/request.js:580:14)
W20160518-08:24:22.841(4.5)? (STDERR) at Object._onImmediate (/home/cyc/Programming/Projects/content/Sources/node_modules/request/request.js:594:7)
W20160518-08:24:22.841(4.5)? (STDERR) at processImmediate [as _immediateCallback] (timers.js:363:15)
现在我有两个问题:
- 如何修复上面的代码?
- 这种方法是在 Meteor 中同步使用请求 npm 模块的最佳方法吗?还是您知道更好的方法?
绑定环境
Meteor.bindEnvironment
只是确保在调用原始函数时使用的上下文中调用回调。它不应该使您的代码看起来是同步的。如果你没有使用它,你的回调将不会在 fiber 中 运行 (这将阻止你执行某些操作)并且你将无法访问某些变量(例如当前用户)。 Crhis Mather 在这个主题上有一个 excellent video(请记住,一些代码有点过时,但核心仍然有效)。
包装一个异步函数
Meteor.wrapAsync
包装函数,这些函数期望使用标准错误优先 2 个参数签名进行回调。由于 request
不遵守这个确切的标准(它使用带有 3 个参数的回调),论坛 post 建议用一个函数包装它,该函数需要带有上述 2 个参数的回调。
惯例是调用 "wrapped" 函数的结果是传递给回调的第二个参数的值(data
),如果有则抛出错误。
因此,像现在这样,你可以用try..catch
块把函数包起来,看看有没有错误。
另一种选择是从不引发错误:
let func = function (options, callback) {
request(options, function (error, response, body) {
callback(null, {response, body, error});
});
};
这将始终生成一个 {response, body, error}
对象,如果没有错误,其中 error
将是 null
。
使用 http 包
我认为 http 包是完全有效的,并且使用方便的方法(例如,一般的 call
,以及特定的 get
和 post
):
例如:
import { HTTP } from 'meteor/http';
const result = HTTP.get('https://my-url.com');
我尝试在 Meteor 1.3.2.4 中使用 request npm package 作为同步。
基于this Meteor guide article,首先我尝试像下面这样使用Meteor.bindEnvironment
:
import request from 'request';
let result = {success: false, error: null, content: ""};
let requestOptions = {
url: <MY-URL-HERE>
};
request(requestOptions, Meteor.bindEnvironment((error, response, html) => {
if (!error && response.statusCode == 200) {
result.success = true;
result.content = html;
result.error = null;
}
else {
result.success = false;
result.content = "";
result.error = error;
}
}));
不过好像还是异步调用。
下一步我尝试在流星论坛上使用基于this answer的Meteor.wrapAsync
,这是下一个尝试代码:
import request from 'request';
let result = {success: false, error: null, content: ""};
let requestOptions = {
url: <MY-URL-HERE>
};
let func = function (options, callback) {
request(options, function (error, response, body) {
console.log("error: " + JSON.stringify(error));
console.log("response: " + JSON.stringify(response));
console.log("body: " + JSON.stringify(body));
callback(error, {response, body});
});
};
let {error, response, body} = syncRequest(requestOptions);
console.log("error2: " + JSON.stringify(error));
console.log("response2: " + JSON.stringify(response));
console.log("body2: " + JSON.stringify(body));
if (response.statusCode == 200) {
result.success = true;
result.content = body;
result.error = null;
}
else {
result.success = false;
result.content = "";
result.error = error;
}
此代码工作正常,但请求包含错误。当请求包含错误时(例如 url 不正确),此中断会出现以下异常:
I20160518-08:24:22.180(4.5)? error: {}
I20160518-08:24:22.181(4.5)? response: undefined
I20160518-08:24:22.182(4.5)? body: undefined
W20160518-08:24:22.839(4.5)? (STDERR) TypeError: The header content contains invalid characters
W20160518-08:24:22.839(4.5)? (STDERR) at Object.Future.wait (/home/cyc/.meteor/packages/meteor-tool/.1.3.2_4.7bk6xv++os.linux.x86_64+web.browser+web.cordova/mt-os.linux.x86_64/dev_bundle/server-lib/node_modules/fibers/future.js:420:15)
W20160518-08:24:22.839(4.5)? (STDERR) at packages/meteor/helpers.js:119:1
W20160518-08:24:22.839(4.5)? (STDERR) at Object.getContent (server/lib/get_content.js:51:26)
W20160518-08:24:22.839(4.5)? (STDERR) at Object.fetch (server/lib/get_content.js:205:27)
W20160518-08:24:22.839(4.5)? (STDERR) at Object.fetchSource (server/lib/get_content.js:369:31)
W20160518-08:24:22.840(4.5)? (STDERR) at [object Object].action (server/controller/postsController.js:79:39)
W20160518-08:24:22.840(4.5)? (STDERR) at [object Object].handle (packages/iron_middleware-stack/lib/handler.js:74:1)
W20160518-08:24:22.840(4.5)? (STDERR) at boundNext (packages/iron_middleware-stack/lib/middleware_stack.js:251:1)
W20160518-08:24:22.840(4.5)? (STDERR) at runWithEnvironment (packages/meteor/dynamics_nodejs.js:110:1)
W20160518-08:24:22.840(4.5)? (STDERR) at packages/meteor/dynamics_nodejs.js:123:1
W20160518-08:24:22.840(4.5)? (STDERR) - - - - -
W20160518-08:24:22.840(4.5)? (STDERR) at ClientRequest.OutgoingMessage.setHeader (http.js:733:13)
W20160518-08:24:22.840(4.5)? (STDERR) at new ClientRequest (http.js:1429:14)
W20160518-08:24:22.840(4.5)? (STDERR) at Object.exports.request (http.js:1899:10)
W20160518-08:24:22.841(4.5)? (STDERR) at Request.start (/home/cyc/Programming/Projects/content/Sources/node_modules/request/request.js:753:32)
W20160518-08:24:22.841(4.5)? (STDERR) at Request.end (/home/cyc/Programming/Projects/content/Sources/node_modules/request/request.js:1418:10)
W20160518-08:24:22.841(4.5)? (STDERR) at end (/home/cyc/Programming/Projects/content/Sources/node_modules/request/request.js:580:14)
W20160518-08:24:22.841(4.5)? (STDERR) at Object._onImmediate (/home/cyc/Programming/Projects/content/Sources/node_modules/request/request.js:594:7)
W20160518-08:24:22.841(4.5)? (STDERR) at processImmediate [as _immediateCallback] (timers.js:363:15)
现在我有两个问题:
- 如何修复上面的代码?
- 这种方法是在 Meteor 中同步使用请求 npm 模块的最佳方法吗?还是您知道更好的方法?
绑定环境
Meteor.bindEnvironment
只是确保在调用原始函数时使用的上下文中调用回调。它不应该使您的代码看起来是同步的。如果你没有使用它,你的回调将不会在 fiber 中 运行 (这将阻止你执行某些操作)并且你将无法访问某些变量(例如当前用户)。 Crhis Mather 在这个主题上有一个 excellent video(请记住,一些代码有点过时,但核心仍然有效)。
包装一个异步函数
Meteor.wrapAsync
包装函数,这些函数期望使用标准错误优先 2 个参数签名进行回调。由于 request
不遵守这个确切的标准(它使用带有 3 个参数的回调),论坛 post 建议用一个函数包装它,该函数需要带有上述 2 个参数的回调。
惯例是调用 "wrapped" 函数的结果是传递给回调的第二个参数的值(data
),如果有则抛出错误。
因此,像现在这样,你可以用try..catch
块把函数包起来,看看有没有错误。
另一种选择是从不引发错误:
let func = function (options, callback) {
request(options, function (error, response, body) {
callback(null, {response, body, error});
});
};
这将始终生成一个 {response, body, error}
对象,如果没有错误,其中 error
将是 null
。
使用 http 包
我认为 http 包是完全有效的,并且使用方便的方法(例如,一般的 call
,以及特定的 get
和 post
):
例如:
import { HTTP } from 'meteor/http';
const result = HTTP.get('https://my-url.com');