DvaJS,基于 Redux 的数据流方案,一个轻量级的应用框架。经典组合 Dva + Ant Design + TypeScript + ES8
UmiJS,蚂蚁金服的底层前端框架,企业级 React 应用框架,开箱即用。
umi + dva
1)根据文件名自动生成路由----约定式路由( nuxt.js / next.js )
2)脚手架能力
3)Mock 数据
dva 的 model 示例代码,返回一个普通的JavaScript对象,包含
- namespace —— 状态对象名称
- state —— 对应 Reducer 的 初始状态
- reducers —— 状态更新
- effects —— action 改变 state,异步请求
- subscriptions ——订阅数据源,可用来监听 history 路由变化,触发 action 加载数据
import _ from 'lodash';
import { api } from 'src/services';
export default {
namespace: 'csi_mobile_compare',
state: {
data: [],
brands: [],
date: [],
angle: [],
brand: [],
platform: [],
province: [],
site: [],
segment: [],
loading: true
},
effects: {
*getCompares({ params, onSuccess }: any, { call, put }: any): any {
yield put({ type: 'addData', data: { loading: true } });
let data = yield call(api.getContent, params);
let brands = yield call(api.getBrands, params);
let date = yield call(api.getDate);
let angle = yield call(api.dictAngle);
let brand = yield call(api.dictBrand);
let platform = yield call(api.dictPlatform);
let province = yield call(api.dictProvince);
let site = yield call(api.dictSite);
let segment = yield call(api.dictSegment);
yield put({
type: 'addData',
data: { data, brands, date, angle, brand, platform, province, site, segment, loading: false }
});
}
},
reducers: {
addData(state: any, rst: any): any {
return { ...state, ...rst.data };
}
}
};
yield call 返回 Promise 对象,只有返回 resolve 方法时,才会执行下一个 yield call 。也就是说接口是串行的,耗时变成1s+1s。当一个接口报错时,后面就执行不了,整个页面 state 就不更新,就像你吃饭被鱼翅卡住一样,再也享受不了后面的美食,有没有很崩溃?
本人在用dva做的项目一直都是多个接口串行的,随着页面功能模块的增加,页面的渲染时间变成1s+1s+1s+...,一度被业务吐槽。个人也在反思,并尝试了一些解决方案。
R1:将多个接口分批串行,每批resolve后就先更新state,达到页面局部渲染的效果。总的渲染时间为1s+1s+1s+...+10s+10s+...
effects: {
*getCompares({ params, onSuccess }: any, { call, put }: any): any {
yield put({ type: 'addData', data: { loading: true } });
let data = yield call(api.getContent, params);
let brands = yield call(api.getBrands, params);
let date = yield call(api.getDate);
yield put({
type: 'addData',
data: { data, brands, date, loading: false }
});
let angle = yield call(api.dictAngle);
let brand = yield call(api.dictBrand);
let platform = yield call(api.dictPlatform);
yield put({
type: 'addData',
data: { angle, brand, platform }
});
let province = yield call(api.dictProvince);
let site = yield call(api.dictSite);
let segment = yield call(api.dictSegment);
yield put({
type: 'addData',
data: { province, site, segment }
});
}
},
该解决方案持续了一段时间,最后几个接口费时太长,简直是10s+10s+10s。突然某一天灵光一闪,这些接口没有任何依赖关系,为何不多个接口并发请求呢???然后就出来了第二个解决方案
R2:分步合并请求,耗时1s,2s,10s....大大缩短了等待时长
effects: {
*getCompares({ params, onSuccess }: any, { call, put }: any): any {
yield put({ type: 'addData', data: { loading: true } });
let data = [];
let brands = [];
let date = [];
let angle = [];
let brand = [];
let platform = [];
let province = [];
let site = [];
let segment = [];
[data, brands, date] = yield [call(api.getContent, params), call(api.getBrands, params), call(api.getDate)];
yield put({
type: 'addData',
data: { data, brands, date, loading: false }
});
[angle, brand, platform] = yield [call(api.dictAngle, call(api.dictBrand)), call(api.dictPlatform)];
yield put({
type: 'addData',
data: { angle, brand, platform }
});
[province, site, segment] = yield [call(api.dictProvince), call(api.dictSite), call(api.dictSegment)];
yield put({
type: 'addData',
data: { province, site, segment }
});
}
},
但还是不最优解???期待再续。。。