简单问题: Nodejs http.get() 如何同步返回給客户端?
简单问题: Nodejs http.get() 如何同步返回給客户端?
嗯嗯嗯,这应该是所有学习 node 的人必须过的一关:
- 使用 http 内置模块,进行url 获取时
- 因为 node 是异步的,从指定 url 下载数据,直到 end 事件发生时,才完成
- 但是,作为一个 post 或是 get 请求过程中,就无法简单的,自然思路的返回数据了,
e.g::
app.post '/chk', (req, res) ->
...
http.get options, (res) ->
data = ''
res.on 'data', (chunk) ->
data += chunk.toString()
res.on 'end', () ->
answer = JSON.parse(data)
console.log answer.success
res.send answer
- 这时,俺用 curl 什么的访问 127.0.0.1/chk ,給个网址
- 那么,返回时,怎么也无法简单的获得 answer
- 除了人工等待几秒,还有什么方案?
ps: 环境是:
- node > v0.6.8
- coffee v 1.2.0
- express v2.5.8
要解决这个问题,我们需要理解 Node.js 的异步特性。在 Node.js 中,处理 HTTP 请求通常需要异步操作来避免阻塞事件循环。因此,直接同步返回数据是不可能的。不过,我们可以使用一些方法来模拟同步行为。
示例代码
以下是一个使用 http.get
方法并将其结果同步返回给客户端的示例代码。这里我们使用了 async/await
来简化异步逻辑:
const express = require('express');
const http = require('http');
const app = express();
app.post('/chk', async (req, res) => {
try {
const options = {
hostname: 'example.com',
port: 80,
path: '/somepath',
method: 'GET'
};
let data = '';
// 使用 promise 包装 http.get
const response = await new Promise((resolve, reject) => {
const req = http.get(options, (res) => {
res.on('data', (chunk) => {
data += chunk;
});
res.on('end', () => {
resolve(data);
});
});
req.on('error', (err) => {
reject(err);
});
});
// 解析响应数据
const answer = JSON.parse(response);
// 返回结果
res.send(answer);
} catch (error) {
res.status(500).send({ error: 'Failed to fetch data' });
}
});
app.listen(3000, () => {
console.log('Server is running on port 3000');
});
解释
-
使用
async/await
: 我们将http.get
封装在一个Promise
中,并使用await
关键字来等待其完成。这样可以使得异步操作看起来像同步代码一样。 -
封装
http.get
: 我们创建一个Promise
,在http.get
完成后解析它。这样我们就可以在await
中等待它完成。 -
错误处理: 使用
try/catch
块来捕获可能发生的错误,并适当地处理它们。 -
发送响应: 在
http.get
完成后,我们将解析的数据作为 JSON 发送给客户端。
这种方法虽然不是真正的同步执行,但通过 async/await
可以使代码更加简洁和易读。希望这能帮助你解决问题!
javascript - Node.js. Http.get() function is not responding. - Stack Overflow http://stackoverflow.com/questions/8893167/node-js-http-get-function-is-not-responding
javascript - Node.js: Parse JSON object - Stack Overflow http://stackoverflow.com/questions/6486208/node-js-parse-json-object
等等,都是从 console 返回給后台,然而前台要怎么办?
app.post '/chk', (req, res) ->
...
http.get options, (gres) ->
data = ''
gres.on 'data', (chunk) ->
data += chunk.toString()
gres.on 'end', () ->
answer = JSON.parse(data)
console.log answer.success
res.end answer
在 res.on 的 end 事件中,不论 res.write/send/end 都吼对象没有这个方法,
::
.../app.coffee:44
return res.end(answer.success);
^
TypeError: Object #<IncomingMessage> has no method 'end'
at IncomingMessage.<anonymous> (/Users/zoomq/Works/@NAE/no.de/urisaok/app.coffee:44:20)
at IncomingMessage.emit (events.js:88:20)
at HTTPParser.onMessageComplete (http.js:137:23)
at Socket.ondata (http.js:1147:24)
at TCP.onread (net.js:354:27)
在 res.on 的 end 事件中,不论 res.write/send/end 都吼对象没有这个方法,
::
.../app.coffee:44
return res.end(answer.success);
^
TypeError: Object #<IncomingMessage> has no method 'end'
at IncomingMessage.<anonymous> (/Users/zoomq/Works/@NAE/no.de/urisaok/app.coffee:44:20)
at IncomingMessage.emit (events.js:88:20)
at HTTPParser.onMessageComplete (http.js:137:23)
at Socket.ondata (http.js:1147:24)
at TCP.onread (net.js:354:27)
在 res.on 的 end 事件中,不论 res.write/send/end 都吼对象没有这个方法,
::
.../app.coffee:44
return res.end(answer.success);
^
TypeError: Object #<IncomingMessage> has no method 'end'
at IncomingMessage.<anonymous> (/Users/zoomq/Works/@NAE/no.de/urisaok/app.coffee:44:20)
at IncomingMessage.emit (events.js:88:20)
at HTTPParser.onMessageComplete (http.js:137:23)
at Socket.ondata (http.js:1147:24)
at TCP.onread (net.js:354:27)
在 res.on 的 end 事件中,不论 res.write/send/end 都吼对象没有这个方法,
::
.../app.coffee:44
return res.end(answer.success);
^
TypeError: Object #<IncomingMessage> has no method 'end'
at IncomingMessage.<anonymous> (/Users/zoomq/Works/@NAE/no.de/urisaok/app.coffee:44:20)
at IncomingMessage.emit (events.js:88:20)
at HTTPParser.onMessageComplete (http.js:137:23)
at Socket.ondata (http.js:1147:24)
at TCP.onread (net.js:354:27)
在 res.on 的 end 事件中,不论 res.write/send/end 都吼对象没有这个方法,
::
.../app.coffee:44
return res.end(answer.success);
^
TypeError: Object #<IncomingMessage> has no method 'end'
at IncomingMessage.<anonymous> (/Users/zoomq/Works/@NAE/no.de/urisaok/app.coffee:44:20)
at IncomingMessage.emit (events.js:88:20)
at HTTPParser.onMessageComplete (http.js:137:23)
at Socket.ondata (http.js:1147:24)
at TCP.onread (net.js:354:27)
在 res.on 的 end 事件中,不论 res.write/send/end 都吼对象没有这个方法,
::
.../app.coffee:44
return res.end(answer.success);
^
TypeError: Object #<IncomingMessage> has no method 'end'
at IncomingMessage.<anonymous> (/Users/zoomq/Works/@NAE/no.de/urisaok/app.coffee:44:20)
at IncomingMessage.emit (events.js:88:20)
at HTTPParser.onMessageComplete (http.js:137:23)
at Socket.ondata (http.js:1147:24)
at TCP.onread (net.js:354:27)
哈哈,pythonic都喜欢coffee
必然的,已经完全无法忍受无排版的代码以及多余的各种东西了,
嗯嗯嗯 ,最后用通用的流氓策略搞掂!
- 找对应的模块 完成异步行为同步返回!
使用dependency injection,把获得的answer注入自定义callbalk中
//post function
function post(url, callback){
app.post(url,function(req,res){
...
res.on('end',function(){
...
callback(answer);
});
}
//good seperation
function sendAnswer(ans){
res.end(ans);
}
//do the job
post('/chk',sendAnswer);
看看有没有什么帮助http://www.9958.pw/post/nodejs_get_html_a
npm install -g xd-synchttp
安装完成后,示例代码如下。
const sync = require('xd-synchttp');
let content = "";
try{
content = sync.http_get('http://www.csdn.net',0);//0为不超时,其他数值为超时秒数
}
catch(err){
console.log(err);
}
对于这个问题,由于 Node.js 的异步特性,直接同步地返回 http.get
的结果是不可能的。你需要处理异步逻辑,让请求的结果在准备好后返回给客户端。
可以使用 Promise 或 async/await 来管理异步操作,使得代码看起来更像同步代码。这里提供一个使用 async/await
的例子:
const express = require('express');
const http = require('http');
const app = express();
app.post('/chk', async (req, res) => {
const options = { /* your options here */ };
try {
const result = await new Promise((resolve, reject) => {
const req = http.get(options, response => {
let data = '';
response.on('data', chunk => data += chunk);
response.on('end', () => resolve(data));
});
req.on('error', reject);
});
const answer = JSON.parse(result);
console.log(answer.success);
res.send(answer);
} catch (error) {
console.error(error);
res.status(500).send({ error: "Failed to fetch data" });
}
});
app.listen(3000, () => console.log('Server running on port 3000'));
上述代码中,我们创建了一个返回 Promise 的函数来处理 http.get
请求,并使用 await
等待其完成。这样就可以在 Express 的路由处理函数中以同步方式编写异步代码。这样做的好处是代码更加清晰,逻辑更容易理解。