成功解决:node作BFF,整合数据,转发请求

问题

项目设计为双后台。

一个是python后台,返回的通用数据,数据都比较原子化。

一个是node后台,作为BFF(Backends For Frontends 服务于前端的后端),为前端提供整合好的数据。

node作为中间服务器,需要多次请求python后台数据,并将其整合成前端需要的形式

本文的问题便是如何整合后台数据并返回

 

前置信息

 

python提供的接口:

spu接口

const API = '/spu?spu=spuname'

const response = {
	code: 200,
	msg: '业务成功',
	data: {
		name: 'spu_name',
		title: 'spu_title',
		pictures: 'pictures',
		skus: [
			'sku1_name',
			'sku2_name',
			'sku3_name',
		]
	}
};

 

sku接口

const API = '/sku?sku=sku_name'

const repsonse = {
	code: 200,
	msg: '业务成功',
	data: {
		name: 'sku_name',
		details: 'details',
		pictures: 'pictures',
		price: '3.99',
	}
}

 

必要的解释

spu:Standard Product Unit,标准产品单元

sku:Stock Keeping Unit,最小货存单位

第一张图,iPhone12mini,这个就是spu,无论是蓝色、绿色,64GB、128GB都是iPhone12mini

第二张图,iPhone12mini-无需合约版-绿色-64GB,这个就是sku,确定到库存里最小最细的一类库存

 

node 目标接口:

预期封装接口

const API = '/spu/details?sku=sku_name'

const response = {
	code: 200,
	msg: '业务成功',
	data: {
		name: 'spu_name',
		title: 'spu_title',
		pictures: 'spu_pictures',
		skus: [
			{
				name: 'sku1_name',
				details: 'sku1_details',
				pictures: 'sku1_pictures',
				price: '1.00',
			},
			{
				name: 'sku2_name',
				details: 'sku2_details',
				pictures: 'sku2_pictures',
				price: '2.00',
			},
			{
				name: 'sku3_name',
				details: 'sku3_details',
				pictures: 'sku3_pictures',
				price: '3.00',
			},
		]
	}
}

 

最终代码

const express = require('express')
const http = require('http')
const axios = require('axios')

var app = express()

const remote = "127.0.0.1"
const port = 8080
const running_port = 3000
const hostname = `http://${remote}:${port}`

app.get('/spu/details', async function(req, res){
    var params = req.query
	var spu = params.spu
	spu = await axios.get(`${hostname}/spu?spu=${spu}`)
	spu = spu.data.data
	if(!spu){
		res.status(500).json({error: '服务器错误'})
	}
	var result = []
	for(sku of spu.skus){
		sku = axios.get(`${hostname}/sku?sku=${sku}`)
		result.push(sku)
	}
	result = await axios.all(result)
	if(!result){
		res.status(500).json({error: '服务器错误'})
	}
	spu.skus = result.map(res => res.data.data)
    res.send(spu)
})

app.all('*', (req, res) => {
	const option = {
      hostname: remote,
      port: port,
      path: req.originalUrl,
      method: req.method,
      headers: req.headers,
	}
	const request = http.request(option, async function(response){
		res.statusCode = response.statusCode
		for(key in response.headers){
			res.header(key, response.headers[key])
		}
		response.pipe(res)
	})
	request.on('error', function(error){
		console.log(error)
	})
    req.pipe(request)
})
.listen(running_port, function(){
    console.log(`Server running on running port ${running_port}`)
})

代码解释

app.get('/spu/details', ...)

async (异步)是javascript里异步函数的标志,如果函数中使用了await(等待)关键字,那么必须将函数声明为异步
async函数返回的是一个Promise对象(一个承诺我会最终有结果的对象^_^),意思是这个会有返回值,但是现在暂时还没有
awai的意思就是函数在这里暂停,当必须得到这个对象里面的一些数据的时候使用
这里我们需要知道spu下面有哪些sku,所以必须等结果出来

axios,是一个异步请求函数库,不使用await函数会返回一个Promise对象
因为sku的获取之间并没有操作是需要互相之间等待的,所以在循环里面,将全部的sku请求发了出去
await axios.all 是等待这个数组里面的所有Promise出结果,这个是一个出错,整个函数就返回错误
result.map 是数组类型的一个方法,返回一个新数组,作用如下图

可以看到,数组的map方法不会改变原数组
原数组中的每个值,都会作为输入,输入到函数之中,得到新的结果
返回这些新结果组成的新数组

app.all('*', ...)

app.all 是接受所有请求的接口,post、get、delete、patch等等方法都会进入这个地方
app.all('*', ()=>{}), *号的意思是接受所有路径的请求
两个联合起来就是接受所有端口,所有路径的意思
这里实现的功能是转发所有的请求

*不会让'/spu/details'接受不到请求吗?
不会。这个express使用的是匹配准确度更高,就优先使用的原则

已标记关键词 清除标记
相关推荐
【为什么还需要学习C++?】 你是否接触很多语言,但从来没有了解过编程语言的本质? 你是否想成为一名资深开发人员,想开发别人做不了的高性能程序? 你是否经常想要窥探大型企业级开发工程的思路,但苦于没有基础只能望洋兴叹?   那么C++就是你个人能力提升,职业之路进阶的不二之选。 【课程特色】 1.课程共19大章节,239课时内容,涵盖数据结构、函数、类、指针、标准库全部知识体系。 2.带你从知识与思想的层面从0构建C++知识框架,分析大型项目实践思路,为你打下坚实的基础。 3.李宁老师结合4大国外顶级C++著的精华为大家推出的《征服C++11》课程。 【学完后我将达到什么水平?】 1.对C++的各个知识能够熟练配置、开发、部署; 2.吊打一切关于C++的笔试面试题; 3.面向物联网的“嵌入式”和面向大型化的“分布式”开发,掌握职业钥匙,把握行业先机。 【面向人群】 1.希望一站式快速入门的C++初学者; 2.希望快速学习 C++、掌握编程要义、修炼内功的开发者; 3.有志于挑战更高级的开发项目,成为资深开发的工程师。 【课程设计】 本课程包含3大模块 基础篇 本篇主要讲解c++的基础概念,包含数据类型、运算符等基本语法,数组、指针、字符串等基本词法,循环、函数、类等基本句法等。 进阶篇 本篇主要讲解编程中常用的一些技能,包含类的高级技术、类的继承、编译链接和命名空间等。 提升篇: 本篇可以帮助学员更加高效的进行c++开发,其中包含类型转换、文件操、异常处理、代码重用等内容。
©️2020 CSDN 皮肤主题: 数字20 设计师:CSDN官方博客 返回首页