Node.js 使用axios拦截器重试请求并将响应转发回前端
我有一些技术问题,是关于我为一家公司申请初级web开发人员职位所做的一项任务。截止日期已经是二月了,但我没能及时完成任务。我仍然想完成它,所以我在这里 首先,我描述应用程序的目的和功能。它用于显示虚拟服装仓库工人的产品列表。目前,用户界面有一个下拉菜单,其中包含三个产品类别:手套、面罩和小珠子。通过下拉菜单中的选择更新产品列表 其次,数据来自两个独立的API。以下是API文档中的引用:Node.js 使用axios拦截器重试请求并将响应转发回前端,node.js,express,error-handling,axios,reverse-proxy,Node.js,Express,Error Handling,Axios,Reverse Proxy,我有一些技术问题,是关于我为一家公司申请初级web开发人员职位所做的一项任务。截止日期已经是二月了,但我没能及时完成任务。我仍然想完成它,所以我在这里 首先,我描述应用程序的目的和功能。它用于显示虚拟服装仓库工人的产品列表。目前,用户界面有一个下拉菜单,其中包含三个产品类别:手套、面罩和小珠子。通过下拉菜单中的选择更新产品列表 其次,数据来自两个独立的API。以下是API文档中的引用: GET /v2/products/:category – Return a listing of produc
GET /v2/products/:category – Return a listing of products in a given category.
GET /v2/availability/:manufacturer – Return a list of availability info.
The APIs are running at https://bad-api-assignment.reaktor.com/.
第一个API返回产品数据,例如名称、颜色、价格和制造商。产品可用性数据(库存、缺货等)来自第二个API
最后是实际问题。我在处理来自提供可用性数据的API的错误响应时遇到问题。该API有一个内置的故意失败案例,其中一些响应以随机方式具有空数组(通常该数组包含约6000个对象)。我正在考虑在Node.js后端处理这个错误案例。下面显示的后端代码仅在理想情况下工作,不会处理错误情况
const express = require( 'express' )
const request = require( 'request' )
const app = express()
app.use( express.static( 'build' ))
/* Sets the needed CORS configuration to response header that is sent to the user's browser. */
app.use( ( req, res, next ) => {
res.header( 'Access-Control-Allow-Origin', '*' )
next()
} )
/* Forwards the frontend request to Reaktor Bad API server and the response back to frontend.
GET /v2/products/:category – Return a listing of products in a given category: gloves, facemasks or beanies.
GET /v2/availability/:manufacturer – Return a list of availability info.
The APIs are running at https://bad-api-assignment.reaktor.com/. */
app.get( '/api', ( req, res ) => {
const category = req.query.category
const manufacturer = req.query.manufacturer
console.log( 'category query parameter: ', category )
console.log( 'manufacturer query parameter: ', manufacturer )
// Reaktor Bad API URL
const baseUrl = 'https://bad-api-assignment.reaktor.com/v2'
// craft full URL, make request to Bad API and forward response
if ( category !== undefined ) {
request( `${baseUrl}/products/${category}`, ( error, response ) => {
console.error( 'category error:', error )
console.log( 'category response & statusCode:', response && response.statusCode )
} ).pipe( res )
}
else if ( manufacturer !== undefined ) {
request( `${baseUrl}/availability/${manufacturer}`, ( error, response ) => {
console.error( 'availability error:', error )
console.log( 'availability response & statusCode:', response && response.statusCode )
} ).pipe( res )
}
else {}
} )
const PORT = process.env.PORT || 3001
app.listen( PORT, () => {
console.log( `Server running on port ${PORT}` )
} )
如您所见,我正在使用express库指定路由。两个不同的前端请求可以以查询参数的形式到达/api
路由:类别
或制造商
。根据查询参数,向API发送适当的请求。此外,路由中使用了现在已弃用的请求库。我想用一个新的替代品来代替它。请求首先从外部API请求数据,然后将其传递给前端。据我所知,这称为反向代理。在前端,我等待所有可用性数据到达(使用axios),然后使用产品数据和可用性数据构建一个阵列。然后将该数组呈现为应用程序用户界面中显示的产品列表
我尝试了几种方法来解决这个问题,最近我了解了axios拦截器。它们是否可用于重试导致错误响应(空数组)的请求,以及如何重试?反向代理怎么样?axios可以做到吗?如何做到?我已经阅读了axios文档,但不理解它。使用express和axios的动机是因为我对它们已经有点熟悉了,请求库不推荐使用。任何帮助都将不胜感激。当我还在学习这些东西时,那些不仅有解决方案代码而且能告诉我其功能的回答对我来说是最有益的。提前谢谢你 我做了一个更简单的操作,但没有使用Axios拦截器,我只是重试失败的承诺,如果您有更复杂的条件,它可以扩展,但基本实现是这样的
/**
* Sleeps for a given number of time
* @param milliseconds milliseconds to sleep
* @returns void promise
*/
export function sleep(milliseconds: number): Promise<void> {
return new Promise((resolve) => setTimeout(resolve, milliseconds));
}
/**
* Wraps a promise like to add retry capability. This is resursive
* @param fn promise to wrap
* @param retries retries remaining
* @param interval interval between retries
* @returns promise
*/
export async function retryable<T>(
fn: PromiseLike<T>,
retries: number = 3,
interval: number = 200
): Promise<T> {
try {
return await fn;
} catch (error) {
if (retries === 0) {
throw error;
}
await sleep(interval);
return await retryable(fn, retries - 1, interval);
}
}
/**
*睡眠一定时间
*@param毫秒睡眠时间
*@返回无效的承诺
*/
导出函数睡眠(毫秒数):承诺{
返回新承诺((解析)=>setTimeout(解析,毫秒));
}
/**
*包装承诺,如添加重试功能。这是死灰复燃
*@param-fn承诺包装
*@param重试剩余的重试次数
*@param间隔重试之间的间隔
*@回报承诺
*/
导出异步函数可重试(
fn:像承诺一样,
重试次数:次数=3次,
间隔:数字=200
):承诺{
试一试{
返回等待fn;
}捕获(错误){
如果(重试次数===0){
投掷误差;
}
等待睡眠(间隔);
返回等待可重试(fn,重试次数-1,间隔);
}
}
我在Axios中使用的是一个会导致错误的拦截器。这样我就可以在客户端模拟故障,而不是在服务器端创建场景
if (failureRate > 0) {
authenticatedClientRef.current.interceptors.request.use((req) => {
if (Math.random() < failureRate) {
throw Error('Intentional failure');
} else {
return req;
}
});
}
if(故障率>0){
authenticatedClientRef.current.interceptors.request.use((req)=>{
if(Math.random()