最近师兄搞了一下蚂蚁金服的 ant-design提供的后台模板框架(基于react)由于这个模板使用的是dva框架,里面各种ES6/ES7的新思想,于是小研究了一下effects。主要是模拟effetcs的异步机制。
ant官方栗子:
export default {
namespace: 'puzzlecards',
state: {
data: [],
counter: 0,
},
//+++++++++++++++++++++++++++主要实现一下功能+++++++++++++++++++++++++++++++++++++++++
effects: {
*queryInitCards(_, sagaEffects) {
const { call, put } = sagaEffects;
const endPointURI = 'https://08ad1pao69.execute-api.us-east-1.amazonaws.com/dev/random_joke';
const puzzle = yield call(request, endPointURI);
yield put({ type: 'addNewCard', payload: puzzle });
yield call(delay, 3000);
const puzzle2 = yield call(request, endPointURI);
yield put({ type: 'addNewCard', payload: puzzle2 });
}
},
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
reducers: {
addNewCard(state, { payload: newCard }) {
const nextCounter = state.counter + 1;
const newCardWithId = { ...newCard, id: nextCounter };
const nextData = state.data.concat(newCardWithId);
return {
data: nextData,
counter: nextCounter,
};
}
},
};
师兄实现的核心代码
let url = "http://xxxx";
let param = { name: "xx", age: 22 };
console.log("before fetch<<<<<<<<<<<<<<<");
let generatorOutter = {
effects: {
* httpGet(_, sagaEffects) {
const { _call, _put } = sagaEffects;
let _param = { url: url, param: param }
let res = yield _call(_httpGet, _param);
console.log(res, "1",processId);
yield _put(callback, res,processId);
console.log(res, "2",processId);
yield _call((param)=>{
console.log("this is not a Promise fnc",processId);
console.log("normal fnc param:",param,processId);
},{ppip:processId})
},
}
}
//数据回调方法
function callback(resData) {
console.log(">>>>>>>>>回调获取的数据<<<<<",processId);
console.log(resData,processId);
}
//主入口
let main = function () {
let generator = generatorOutter.effects;
for (let fnc in generator) {
let _step = generator[fnc](_, sagaEffects);
sagaEffects.setStep(_step);
_step.next();
}
}
let sagaEffects = {
step: new Object(),
setStep: function (_step) {
this.step = _step;
},
/*getStep: function () {
return this.step;
},*/
_call: function (fnc, param) {
let step = sagaEffects.step;
if (sagaEffects._chargePromise(fnc)) {
console.log("传入Promise",processId);
fnc(param).then(res => {
if (step) step.next(res);
})
} else {
sagaEffects._async_call(fnc, param).then((res)=>{
if (step) step.next(res);
});
}
},
_put: function (callback, param) {
sagaEffects._async_call(callback, param).then((res)=>{
sagaEffects.step.next(res);
});
},
_async_call:async function(fnc, param){
return await fnc(param);
},
_chargePromise(fnc) {
if (fnc !== null && ( typeof fnc === 'function') &&typeof fnc.then === 'function')
return true;
return false;
},
_closeGenerator(){}
}
async function _httpGet({url, param}) {
url = handlerParams(url, param);
try {
const response = await fetch(url, { credentials: 'include', method: 'GET' });
return await response.json();
} catch (e) {
console.log(e);
}
}
//开始测试
main();
看下效果,我同时调用了6次分别传入不同的id以区别,id顺序不是1-6说明异步有效
看下网络请求,同时发起
End
这里我主要实现了sagaEffects中的call和put方法,也就是传入的方法的执行和返回数据,ES6的异步还是很有意思的,代码简洁了不少。
2018-11-19