開發(fā)過程中被各種async弄到破防,因此手擼了幾個工具類保證代碼穩(wěn)定性狂票,話不多說直接上代碼龟再,文件后綴需要改成.ts比如PromiseUtil.ts
export function Promise_withResolver<T>() {
let resolve: (value: T) => void = undefined
let reject: (err: Error) => void = undefined
const promise = new Promise<T>((res, rej) => {
resolve = res
reject = rej
})
return {
promise: promise,
resolve: resolve,
reject: reject
}
}
該代碼復(fù)刻js最新Promise的API停士,將resolver和reject從Promise中拆除迟隅,使數(shù)據(jù)的觀察和觸發(fā)分離,上場景
掃碼組件初始化需要XComponent組件onLoad及權(quán)限判斷成功后才開始掃碼,掃碼尺寸需要匹配XComponent寬高
private areaCallback = Promise_withResolver<Area>()
private loadCallback = Promise_withResolver<boolean>()
private permissionCallback = Promise_withResolver<boolean>()
private checkInitCallback = Promise.all([this.areaCallback.promise, this.loadCallback.promise, this.permissionCallback.promise])
build(){
XComponent({
id: 'componentId',
type: 'surface',
controller: this.mXComponentController
})
.onAreaChange((_, newValue) => {
this.areaCallback.resolve(newValue)
})
.onLoad(() => {
this.loadCallback.resolve(true)
})
.size(FullScreen)
}
aboutToAppear(): void {
this.checkInitCallback.then((value) => {
this.surfaceId = this.mXComponentController.getXComponentSurfaceId();
this.cameraHeight = value[0].height as number
this.cameraWidth = value[0].width as number
if (value[2]) {
this.vm.changeState(SCAN)
} else {
this.vm.changeState(NO_PERMISSION)
}
})
}
在進行頁面的初始化時有很多場景觸發(fā)接口去請求默認數(shù)據(jù)攻礼,相同的請求經(jīng)常重復(fù)發(fā)送业踢,所以想起了Synchronize原理,ts中實現(xiàn)如下
export function LazyInit<T>(block: () => Promise<T>) {
const waitQueue: Array<(value: T) => void> = []
let init: boolean | undefined = undefined
let value: T
return () => {
if (init === undefined) {
return new Promise<T>((res, rej) => {
init = false
block().then((value) => {
init = true
res(value)
while (waitQueue.length != 0) {
waitQueue.pop()?.(value)
}
})
})
} else if (init) {
return Promise.resolve(value)
} else {
const resolver = Promise_withResolver<T>()
waitQueue.push(resolver.resolve)
return resolver.promise
}
}
}
直接上場景
waitAndReturn() : Promise<string>{
return new Promise((res) => {
setTimeout(res, 5000, "123")
})
}
private data = LazyInit(async () => {
return await this.waitAndReturn()
})
Logger.debug("gscgsc1", `start`)
this.data().then((value : string) => {
Logger.debug("gscgsc1", `${value}`)
})
this.data().then((value : string) => {
Logger.debug("gscgsc2", `${value}`)
})
this.data().then((value : string) => {
Logger.debug("gscgsc3", `${value}`)
})
this.data().then((value : string) => {
Logger.debug("gscgsc4", `${value}`)
})
this.data().then((value : string) => {
Logger.debug("gscgsc5", `${value}`)
})
運行截圖如下
上面的LazyInit返回的是Promise礁扮,有時我們需要在全局變量初始化時進行懶加載聲明知举,類似kotlin的by lazy,將上面的功能簡化一下如下
export function byLazy<T>(block: () => T): () => T {
let value: T | undefined
return () => {
if (!value) {
value = block()
}
return value
}
}
上才藝
private n = byLazy(() => {
Logger.debug("gscgsc", `math random`)
return Math.random()
})
Logger.debug("gscgsc", 'start')
Logger.debug("gscgsc", `${this.n()}`)
Logger.debug("gscgsc", `${this.n()}`)
Logger.debug("gscgsc", `${this.n()}`)
Logger.debug("gscgsc", 'end')
日志如下
破費科特