使用Express、Node.JS和Require模块进行外部API调用

26

我有一个路由如下:

var express = require('express');
var router = express.Router();
var request = require('request');

router.get('/', function(req, res, next) {
  request({
    uri: 'http://www.giantbomb.com/api/search',
    qs: {
      api_key: '123456',
      query: 'World of Warcraft: Legion'
    },
    function(error, response, body) {
      if (!error && response.statusCode === 200) {
        console.log(body)
      }
    }
  });
});

module.exports = router;

我正在尝试调用Giant Bomb API,以获取有关《魔兽世界》的任何数据。

问题是,该路由只是加载;它没有做任何事情,也没有超时,只是一直在加载。

我不知道我哪里做错了,但话说回来……我也不知道什么是正确的。我正试图边学习边前进。

任何帮助都将是极好的。

谢谢


第一个答案应该会给你一些线索,但是,你能详细说明一下“它只是持续加载”吗?你的意思是请求永远不会完成吗?路由永远不会解析吗?你有任何迹象表明实际情况是这样吗?还是你只是没有得到响应? - Christopher Ronning
你的请求中 qs 代表什么意思? - Ralph David Abernathy
4个回答

48

您需要将从 request() 获取的数据作为响应发送回原始的网络服务器请求。因为您没有发送任何响应,所以它一直在持续加载,因此浏览器一直在等待响应返回,最终会超时。

由于 request() 支持流,您可以使用 .pipe() 对数据进行简单的响应,如下所示。

var express = require('express');
var router = express.Router();
var request = require('request');

router.get('/', function(req, res, next) {
  request({
    uri: 'http://www.giantbomb.com/api/search',
    qs: {
      api_key: '123456',
      query: 'World of Warcraft: Legion'
    }
  }).pipe(res);
});

module.exports = router;

这将把request()的结果通过.pipe()传递到res对象中,并将其作为原始http请求的响应。

相关答案请看这里:如何将请求代理回响应


2021年编辑。 request()库现已弃用,不建议在新代码中使用。有很多替代品可供选择。我最喜欢的是got()库。可以像这样使用它来完成上述操作。这还升级使用了pipeline()函数,它是具有更完整错误处理功能的.pipe()的更好版本。

const router = require('express').Router();
const got = require('got');
const { pipeline } = require('stream');

router.get('/', function(req, res) {
  const dataStream = got.stream({
      uri: 'http://www.giantbomb.com/api/search',
      qs: {
        api_key: '123456',
        query: 'World of Warcraft: Legion'
      }
  });
  pipeline(dataStream, res, (err) => {
      if (err) {
          console.log(err);
          res.sendStatus(500);
      }
  });
});

module.exports = router;

很棒的答案。我正在尝试使用类似的设置,但我还想使用Node apicache。鉴于apicacheexpress兼容良好,这个设置将有助于中间件缓存外部API响应。 - Anjan Biswas
request 已于2020年2月11日被弃用。 - Jaydeep Mor
@JaydeepMor - 我添加了使用 got() 库的答案版本。 - jfriend00

8
对于 Laravel 用户,
首先,如果没有安装,请安装 npm i axios 包。
var axios = require('axios');

var config = {
    /* Your settings here like Accept / Headers etc. */
}

axios.get('http://local.dev/api/v1/users', config)
.then(function(response) {
    console.log(response.data);
    console.log(response.status);
    console.log(response.statusText);
    console.log(response.headers);
    console.log(response.config);
});

希望它能帮助某人!


4

在Express中的每个路由中,必须发送一个响应(部分或完整)或调用next,或同时执行这两个操作。但是您的路由处理程序都没有做到。请尝试:

var express = require('express');
var router = express.Router();
var request = require('request');

router.get('/', function(req, res, next) {
  request({
    uri: 'http://www.giantbomb.com/api/search',
    qs: {
      api_key: '123456',
      query: 'World of Warcraft: Legion'
    },
    function(error, response, body) {
      if (!error && response.statusCode === 200) {
        console.log(body);
        res.json(body);
      } else {
        res.json(error);
      }
    }
  });
});

module.exports = router;

并查看此路由处理程序响应的数据。


谢谢您的输入,但不幸的是我得到了相同的结果。如果我让页面加载足够长的时间,会出现一个错误提示页面无法工作,并且没有发送任何内容。 - Dave Melia
1
我尝试按照这个解决方案,但是“Request”模块已经被弃用了。 - ZIS

3

2022年

在Node中

const fetch = (...args) => import('node-fetch')
  .then(({default: fetch}) => fetch(...args));

app.get('/checkDobleAPI', async (req, res) => {
  try {
    const apiResponse = await fetch(
     'https://jsonplaceholder.typicode.com/posts')
    const apiResponseJson = await apiResponse.json()

    console.log(apiResponseJson)
    res.send('Running ')
  } catch (err) {
    console.log(err)
    res.status(500).send('Something went wrong')
  }
})


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接