本文转载自:众成翻译
译者:网络埋伏纪事
链接:http://www.zcfy.cc/article/1758
原文:https://blog.risingstack.com/node-hero-node-js-request-module-tutorial/
在如下教程中,将学习 HTTP 协议的基础知识,以及如何使用 Node.js 的 request 模块从外部源获取资源。
什么是 HTTP?
HTTP 代表超文本传输协议(Hypertext Transfer Protocol)。HTTP 作为在客户机-服务器计算模型中的请求-响应协议。
HTTP 状态码
在深入与其它 API 的通讯之前,我们来回顾一下在此过程中会遇到的 HTTP 状态码。状态码描述了请求的结果,它对错误处理是必不可少的。
1xx - 响应还没完成(Informational)
2xx - 成功:这些状态码表示请求被接收并正确处理了。最常见的成功响应码是
200 OK
、201 Created
和204 No Content
。3xx - 重定向: 这组状态码表示要完成请求,客户端必须要做一些额外的操作。最常见的重定向响应码是
301 Moved Permanently
、304 Not Modified
。4xx - 客户端错误: 这类状态码被用在客户端发送的请求出现了某种错误时。服务器响应通常会包含了对错误的解释。最常见的客户端错误码是
400 Bad Request
、401 Unauthorized
、403 Forbidden
、404 Not Found
、409 Conflict
。5xx - 服务器错误: 当服务器由于某些错误不能完成有效的请求时,就发送这些状态码。原因可能是代码中的一个 bug,或者一些临时或者永久性的无能。最常见的服务器错误状态码是
500 Internal Server Error
、503 Service Unavailable
。如果你想学习更多有关 HTTP 状态码的知识,可以在这里找到详细的解释。
向外部 API 发送请求
在 Node 中,连接到外部 API 是很简单的。只需要 require 核心 HTTP 模块,然后开始发送请求即可。
当然,有更好的方式来调用外部端点。在 NPM 上可以找到很多让这个过程更容易的模块。例如,两个最流行的模块是 request 和 superagent。
这两个模块都有错误优先的回调接口,这就会导致一些问题(我打赌你已经听说过回调地狱),但是幸运的是我们可以访问封装了 Promise 的版本。
使用 Node.js Request 模块
request-promise 模块 的使用很简单。从 NPM 安装它之后,只需要 require 它:
const request = require('request-promise')
发送一个 GET 请求也那么简单:
const options = {
method: 'GET',
uri: 'https://risingstack.com'
}
request(options)
.then(function (response) {
// Request was successful, use the response object at will
})
.catch(function (err) {
// Something bad happened, handle the error
})
如果调用一个 JSON API,你可能会想让 request-promise 自动解析响应。此时,只需要将其添加到 request 选项即可:
json: true
POST 请求的工作方式也类似:
const options = {
method: 'POST',
uri: 'https://risingstack.com/login',
body: {
foo: 'bar'
},
json: true
// JSON stringifies the body automatically
}
request(options)
.then(function (response) {
// Handle the response
})
.catch(function (err) {
// Deal with the error
})
要添加查询字符串参数,只需要将 qs
属性添加到 options 对象:
const options = {
method: 'GET',
uri: 'https://risingstack.com',
qs: {
limit: 10,
skip: 20,
sort: 'asc'
}
}
这会让请求 URL 变为:https://risingstack.com?limit=10&skip=20&sort=asc
。
还可以用添加查询参数同样的方式来定义所有请求头:
const options = {
method: 'GET',
uri: 'https://risingstack.com',
headers: {
'User-Agent': 'Request-Promise',
'Authorization': 'Basic QWxhZGRpbjpPcGVuU2VzYW1l'
}
}
错误处理
错误处理是对外部 API 发起请求的重要部分,因为不能确保会发生什么。除了客户端错误以外,服务器会响应一个错误,或者就发送一个错误或者不一致格式的数据。在试着处理响应时,要记住这些。此外,对每次请求都使用 catch
也是一个避免外部服务让服务器崩溃的好办法。
综合
既然已经学过如何创建一个 Node.js HTTP 服务器,如何渲染 HTTP 页面,如何从外部 API 获取数据,那么现在就到了将它们放在一起的时候了!
在本例中,我们将创建一个小型 Express 应用程序,该程序基于城市名渲染当前的天气条件。
要获取 AccuWeather API key,请访问 Accuweather 开发者网站。
const express = require('express')
const rp = require('request-promise')
const exphbs = require('express-handlebars')
const app = express()
app.engine('.hbs', exphbs({
defaultLayout: 'main',
extname: '.hbs',
layoutsDir: path.join(__dirname, 'views/layouts')
}))
app.set('view engine', '.hbs')
app.set('views', path.join(__dirname, 'views'))
app.get('/:city', (req, res) => {
rp({
uri: 'http://apidev.accuweather.com/locations/v1/search',
qs: {
q: req.params.city,
apiKey: 'api-key'
// Use your accuweather API key here
},
json: true
})
.then((data) => {
res.render('index', data)
})
.catch((err) => {
console.log(err)
res.render('error')
})
})
app.listen(3000)
上面的示例做如下事情:
创建一个 Express 服务器
设置 handlebars 结构 - 对于
.hbs
文件,请参考 Node.js HTTP 教程-
发送请求给外部 API
如果一切顺利,就渲染页面
否则,就显示错误页并记录错误
下一步
下章将学习如何正确组织 Node.js 项目。