Skip to content

Commit

Permalink
update
Browse files Browse the repository at this point in the history
  • Loading branch information
zhangfisher committed Aug 1, 2024
1 parent 43ee03b commit a20693c
Show file tree
Hide file tree
Showing 4 changed files with 58 additions and 15 deletions.
50 changes: 47 additions & 3 deletions packages/reactive/src/__tests__/async/funcs.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,11 @@
*
* 测试计算属性的getter的第二个参数的各项功能
*
* - 不可重入
* - 中止信号
* - 重试
*
*
*/


Expand All @@ -11,7 +16,8 @@ import { delay } from "flex-tools/async/delay"



describe("异步计算控制功能",()=>{
describe("异步计算高级控制功能",()=>{

// 注意:重入时仅会被忽略而不是产生错误
test("控制计算函数的执行的不允许重入执行",()=>{
let cancelCount:number =0
Expand Down Expand Up @@ -135,19 +141,57 @@ describe("异步计算控制功能",()=>{
price:2,
count:3,
total:computed(async (_,{})=>{
count++
throw new Error("error")
},['price','count'],{id:'x',retry:[5,100]})
},{onceComputed:true})
store.on("computed:error",()=>{
expect(store.state.total.retry).toBe(0)
})
store.watch((valuePath)=>{
retryValues.push(store.state.total.retry)
if(retryValues.length===5){
if(valuePath.some(path=>path[0]==='total' && path[1]==='retry')){
retryValues.push(store.state.total.retry)
}
// 第一次运行出错,再重试5次,因此retry值为5,4,3,2,1,0
if(retryValues.length===6){
expect(retryValues).toEqual([5,4,3,2,1,0])
resolve()
}
},['total'])
})
},0)

test("当执行超时的默认行为",()=>{
// 执行时loading=true,然后超时后自动设置loading=false,error=TIMEOUT
return new Promise<void>((resolve)=>{
const store = createStore({
price:2,
count:3,
total:computed(async (scope,{})=>{
await delay(500)
return scope.price * scope.count
},['price','count'],{id:'x',timeout:100})
})

store.on("computed:cancel",({reason})=>{
expect(reason).toBe("timeout")
resolve()
})
store.state.total
})
})
test("当执行超时触发错误并导致重试",()=>{
// 执行时loading=true,然后超时后自动设置loading=false,error=TIMEOUT
return new Promise<void>((resolve)=>{
const store = createStore({
price:2,
count:3,
total:computed(async (scope,{})=>{
await delay(500)
return scope.price * scope.count
},['price','count'],{id:'x',timeout:100})
})
})
})

})
16 changes: 9 additions & 7 deletions packages/reactive/src/computed/async.ts
Original file line number Diff line number Diff line change
Expand Up @@ -99,11 +99,13 @@ async function executeComputedGetter<T extends StoreDefine>(draft:any,computedRu
hasAbort=true
})
let hasError=false
let hasTimeout=false
let computedResult:any

for(let i=0;i<retryCount+1;i++){
hasError=false
let timerId:any,countdownId:any,isTimeout=false
hasTimeout=false
let timerId:any,countdownId:any
const afterUpdated={} // 保存执行完成后需要更新的内容,以便在最后一次执行后更新状态
try {
// 处理超时参数和倒计时
Expand All @@ -116,7 +118,7 @@ async function executeComputedGetter<T extends StoreDefine>(draft:any,computedRu
// 超时处理
if(timeoutValue>0){
timerId = setTimeout(()=>{
isTimeout=true
hasTimeout=true
if(typeof(timeoutCallback)=='function') timeoutCallback()
if(!hasError){
clearInterval(countdownId)
Expand All @@ -134,12 +136,12 @@ async function executeComputedGetter<T extends StoreDefine>(draft:any,computedRu
// 执行计算函数
computedResult = await getter.call(thisDraft, scopeDraft,computedParams);
if(hasAbort) throw new Error("Abort")
if(!isTimeout){
if(!hasTimeout){
Object.assign(afterUpdated,{result:computedResult,error:null,timeout:0})
}
}catch (e:any) {
hasError = true
if(!isTimeout){
if(!hasTimeout){
Object.assign(afterUpdated,{error:getError(e).message,timeout:0})
}
/// 启用重试
Expand All @@ -151,7 +153,7 @@ async function executeComputedGetter<T extends StoreDefine>(draft:any,computedRu
clearInterval(countdownId)
// 重试时不更新loading状态
if(!hasError || (i==retryCount)) Object.assign(afterUpdated,{loading:false})
if((!hasError && !isTimeout)){
if((!hasError && !hasTimeout)){
Object.assign(afterUpdated,{error:null})
}
updateAsyncComputedState(setState,resultPath,afterUpdated)
Expand All @@ -165,8 +167,8 @@ async function executeComputedGetter<T extends StoreDefine>(draft:any,computedRu
}
}
// 计算完成后触发事件
if(hasAbort){
store.emit("computed:cancel",{path:valuePath,id,reason:'abort'})
if(hasAbort || hasTimeout){
store.emit("computed:cancel",{path:valuePath,id,reason:hasTimeout ? 'timeout' : 'abort'})
}else if(hasError){
store.emit("computed:error",{path:valuePath,id,error:hasError})
}else{
Expand Down
2 changes: 1 addition & 1 deletion packages/reactive/src/store/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,7 @@ export type StoreEvents = {
'computed:created' : ComputedObject // 当计算对象创建时
'computed:done' : {path:string[],id:string,value:any} // 当计算函数执行成功后
'computed:error' : {path:string[],id:string,error:any} // 当计算函数执行出错时
'computed:cancel' : {path:string[],id:string,reason:string} // 当计算函数被取消时
'computed:cancel' : {path:string[],id:string,reason:'timeout' | 'abort' | 'reentry' | 'error'} // 当计算函数被取消时
};


Expand Down
5 changes: 1 addition & 4 deletions packages/reactive/src/watch/install.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
import { flush } from "helux"
import { OBJECT_PATH_DELIMITER } from "../consts"
import { IStore, StoreDefine } from "../store/types"
import { IComputeParams } from "../types"
import { setVal } from "../utils"
import { WatchDescriptor } from "./types"
import { IReactiveReadHookParams } from "../reactives/types"
Expand Down Expand Up @@ -33,8 +31,7 @@ export function installWatch<T extends StoreDefine>(params:IReactiveReadHookPara
// @ts-ignore
store.stateCtx.setState((draft)=>{
setVal(draft,params.path,watchDescriptor.options.initial)
})
flush(store.stateCtx.state as any)
})
}
return watchObject
}
Expand Down

0 comments on commit a20693c

Please sign in to comment.