Nodejs axios 回调问题

Nodejs axios 回调问题

浏览器发起请求,后端 node.js 收到浏览器请求后用 axios 请求一个接口,如何把接口的返回结果给浏览器?

const http = require('http')
const axios = require('axios')
const qs = require('qs')
var request = require('request');

//    返回一个 Server 实例
const server = http.createServer()

async function getData (){
    let obj = {
        'type': "1"
    }

    url = "http://httpbin.org/post"
    const promise = axios.post(url, qs.stringify(obj), {
        headers: {
            'Content-Type': 'application/x-www-form-urlencoded;charset=UTF-8',
            'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36'
        }
    })

    const dataPromise = promise.then((response)=>response.data)
    return dataPromise
}


server.on('request', function (request, response) {

    console.log('收到客户端的请求了,请求路径是:' + request.url)

    response.write('hello')
    getData().then((res) => {
        // response.write(res)
        console.log(res)  //res 怎么返回给前端
    })
    // 告诉客户端,我的话说完了,你可以呈递给用户了
    response.end()
})

server.listen(3000, function () {
    console.log('服务器启动成功了,http://127.0.0.1:3000/')
})

14 回复

response.end() 放到 getData.then 的回调里边


浏览器可以直接用 axios,直接在浏览器层面用 axios 请求就好了

如果你自己想要包装的话,就把你 node.js 里的结果写成一个 api 服务,然后再在浏览器里请求这个 api 拿到结果就好了

1 楼是对的;
或者用 async/await,node 服务端 await getData()之后再返回给浏览器

我怎么感觉你这个代码我看不明白,async 搭配 then ??? 然后 dataPromise 返回的是一个 promise 啊不是结果啊,response.end()也写错位置了,我感觉你没搞懂 async/await,和 promise

我猜你是想把 getData 拿到的数据 response.end()过去给客户端,但是 getData 是个异步,是吧?
那可以这样写
async function getData(callback) {
const res = await axios.post(url)
callback(res)
}
server.on(‘request’, function (request, response) {
getData(res => {
response.end(res)
})
})

既然用了 async await 就没啥必要用其他复杂的用法

3L 说的也对,但是你需要要把 function (request, response)改为 async 函数
都可以

回复没法格式化代码,你自己贴到编辑器里格式化一下吧。

<br>const http = require('http');<br><br>const server = http.createServer((request, response) =&gt; {<br> console.log('收到浏览器请求流。');<br><br> // 构造发出请求的 URL<br> const url = new URL('<a target="_blank" href="http://httpbin.org/post');" rel="nofollow noopener">http://httpbin.org/post');</a><br> // 添加 Search,也就是 Query string<br> url.search = new URLSearchParams({<br> 'type': "1",<br> });<br><br> // 向 httpbin 发送请求流<br> const req = http.request(<br> url,<br> {<br> "method": "POST",<br> "headers": {<br> "Content-Type": "application/x-www-form-urlencoded;charset=UTF-8",<br> "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36",<br> },<br> },<br> res =&gt; {<br> console.log('收到了 httpbin 返回流');<br> <br> console.log('将 httpbin 返回流对接到浏览器的返回流。');<br> res.pipe(response);<br> },<br> );<br> <br> // 结束 httpbin 请求流<br> req.end();<br>});<br><br>server.listen(3000);<br>

题主这个需求有很多种方式可以实现,最简单的是流( Stream )。

浏览器向这个 node 服务发送请求的时候,node 服务会接收到一个来自浏览器的请求流,然后 node 服务向 httpbin 发送一个请求流,httpbin 返回一个返回流,然后像接水管管道一样把 httpbin 的返回流接在 node 服务即将返回给浏览器的返回流,浏览器最终收到了数据。

用流的好处就是不需要自己重建返回给浏览器的返回结构,直接复用上游的返回结构;另一方面 node 服务不需要缓存 httpbin 的整个返回数据,用 async/await 的方案通常会把 httpbin 返回的数据整个存在 node 服务的内存里,小量数据还好,如果是下载大文件的话有撑爆内存的风险。

http 模块的文档在这:
https://nodejs.org/api/http.html

http.createServer 里的回调函数的两个参数类型:
https://nodejs.org/api/http.html#http_class_http_incomingmessage
https://nodejs.org/api/http.html#http_class_http_serverresponse

你可以看到这两个类型都是“Extends: <Stream>”即继承自 Stream,Stream 的文档在这里:
https://nodejs.org/api/stream.html

node 服务返回给浏览器,以及 node 服务发请求给 httpbin,都是属于可写流( Writable Stream ),可写流在写完之后必须调用 end 来结束流。
httpbin 返回给 node 服务的流是可读流( Readable Stream ),你可以把可读流用管道方法( pipe )对接到一个可写流上。

哪有这么麻烦?
async function getData() {
const res = await axios.post();
return res.data;
}

server.on(‘request’, async function (req, res) {
const data = await getData();

res.write(data);
res.end();
})

对,前面用 async/await 试过没实现,没改全

你这个听起来就像是个代理服务,把整个请求转发给另一个地址,我这几天正好做了这个,可以看看这个库: https://www.npmjs.com/package/http-proxy-middleware ,在这里找找例子: https://codexp.io/npm/1/http-proxy-middleware,express,axios,qs

我做的是把请求转给 elasticsearch ,用的是这个例子: https://github.com/appbaseio-apps/reactivesearch-proxy-server/blob/master/index.js

想知道 V2EX 不支持 markdown 语法吗, 看着那么留言里写代码都是没有高亮和 index 的贼难受.😣

在Node.js中使用axios进行HTTP请求时,处理回调(callbacks)和异步操作是非常重要的。axios基于Promise设计,因此更推荐使用Promise或async/await来处理异步请求,而不是传统的回调函数方式。这不仅能提高代码的可读性,还能减少回调地狱(callback hell)的问题。

以下是一个使用axios结合async/await的示例代码:

const axios = require('axios');

async function fetchData() {
    try {
        const response = await axios.get('https://api.example.com/data');
        console.log('Response data:', response.data);
    } catch (error) {
        console.error('Error fetching data:', error);
    }
}

fetchData();

在这个例子中,fetchData是一个异步函数(由async关键字定义)。它使用await关键字等待axios请求的完成。如果请求成功,它会打印响应数据;如果请求失败,它会捕获并打印错误信息。

如果你坚持使用回调函数的方式,虽然不推荐,但也可以这样做:

const axios = require('axios');

axios.get('https://api.example.com/data', function(error, response) {
    if (error) {
        console.error('Error fetching data:', error);
    } else {
        console.log('Response data:', response.data);
    }
});

在这个回调版本的代码中,axios请求的结果会传递给一个回调函数,该函数检查是否有错误,并相应地处理响应数据或错误信息。然而,这种方法不如使用Promise或async/await来得直观和易于维护。

回到顶部