停更原因
- 没有学到新的知识,现有的知识体系已经能支撑我完成大部分工作任务了,即使平时有学习到一些零碎的新的知识,但是不够系统,不能构成新的文章输出。
- 不想写一些随便搜搜就有一大坨的东西,特别是都有官方文档了,就不会再写了,总之就是写给自己看,并且能在工作中随时翻阅的知识。
- 整天都在口吐芬芳,表面上在重构代码,实际上在怀疑这个世界设计不合理
- 懒
白天属于1988
为了完成和新人少于的约定,我还是连夜将这篇水文写完得了,本来白天就属于1988的,还加上失眠,估计周日是已经过去了。
简单介绍
IoC,控制反转,将设计好的对象交给IoC容器创建并管理;例如本例中将想要获取到的对象交给vuex管理,我们将封装并定义一套简单的管理特定对象的机制,从而实现简单的IoC容器功能。
DI,依赖注入,容器动态的将某个依赖关系注入到组件之中;例如本例中组件将依赖IoC容器提供的对象,然后通过组件的具名作用域注入到特定对象中。
vuex,是一个专为vue应用程序开发的状态管理模式。它采用集中式存储管理应用的所有组件的状态,并以相应的规则保证状态以一种可预测的方式发生变化。
接口缓存、自动请求、对象管理解决了什么问题
如果现有后端是微服务架构,微服务之间界限划分清晰,导致前端获取数据需要从不同微服务获取相应的数据,然后组合到一些才能正常显示。
例如:商品列表页面数据需要从营销微服务获取商品的价格和名称等信息列表,然后提取物料id列表到物料微服务获取物料的信息列表,物料微服务主要是负责储存图片,然后将两个列表信息组合。
诸如此类还有店铺微服务,并且多个页面会遇到这样列表展示的问题;
- 所以我们可以设计一套对象管理机制,自动加载我们所需要的物料数据,而不需要我们手动去请求,即IoC容器;
- 并且通过某种方案自动注入到我们声明的对象中,供我们使用,即DI;
- 最后也可以尝试在IoC容器的加入缓存机制,这样可以避免重复的请求;
步骤分析(以商品列表为例)
出示容器
- 首先还是正常获取营销的商品列表信息,然后直接写入data准备渲染数据
- 然后封装一个物料组件,提供一个具名插槽,准备将获取到的单个物料信息返回到页面渲染
- 紧接着就是走actions去添加物料id,最后走getters获取单个物料信息,并设置到data
DI
<template>
<view>
<slot :cacheMaterial="cacheMaterial"></slot>
</view>
</template>
<script>
export default {
props: {materialId: String},
data() {
return {
cacheMaterial: {
materialCarouse: [],
},
};
},
async created() {
await this.$store.dispatch("addMaterialId", this.materialId);
this.cacheMaterial = this.$store.getters.getCacheMaterial(this.materialId);
},
};
利用事件循环机制获取多个物料id
- 因为获取数据是在created中,代表所有组件数据还在初始化,视图还未渲染,线程依然在执行js文件(只有一个线程);
- 首先在开始之前,通过state中的缓存过滤了所有已经重复请求过的物料id,否则都会加入到全局newMaterialIdList列表中
- 当第一个组件物料id进入的时候,会执行一个setTimeOut方法,众所周知,这个方法会被加入任务队列中,等待主队列执行完;
- 然后第二个、第三个等会依次的执行addMaterialId方法,因为可以通过newMaterialIdList长度判断当前进入的组件不是第一个组件了,所以我就返回一个Promise函数,但是我并不准备直接执行resolve方法,而是将resolve加入到一个materialResolveList列表中,等待时机执行;
- 了解过Promise原理的人应该知道,resolve本质上还是一个回调函数,因为Promise只是一些列操作的语法糖而已。
- 这样我可以保证第一个以后的所有物料id和组件的Promise回调函数都被收集起来了;
- 根据事件循环机制,此时开始执行任务队列里面setTimeOut的回调方法;
- 然后将newMaterialIdList去重后开始请求数据,然后将数据添加到state中;
- 最后执行所有的resolve方法,保证第二个以后的所有组件的回调函数都被执行;
- 其他微服务例如店铺,就可以如法炮制
IoC
const setTimeoutPromise = time => new Promise(resolve => setTimeout(resolve, time || 0));
const newMaterialIdList = [];
const materialResolveList = [];
const initMaterialInfo = () => {
materialResolveList.forEach(resolve => resolve());
materialResolveList.length = 0;
newMaterialIdList.length = 0;
};
const addMaterialId = async (context, materialId) => {
const materialIdList = context.state.cacheMaterialList.map(item => item.materialId);
if (materialIdList.indexOf(materialId) !== -1) return null;
newMaterialIdList.push(materialId);
if (newMaterialIdList.length !== 1) return await new Promise(resolve => materialResolveList.push(resolve));
await setTimeoutPromise();
try {
const materialList = await getMaterialaggregateMaterialList({
materialIds: { ids: [...new Set(newMaterialIdList)] },
});
context.commit("setMaterialIdList", materialList);
} finally {
initMaterialInfo();
}
};
画图示意
这样的应用设计场景本来就很极端,除非刚好公司后端采用的DDD领域驱动设计,子域划分的足够清晰,并且有且仅有一个后端leader,又恰好没有使用Koa、Express、Egg.js或者GraphQl来实现BFF层;