在Arkts中用ts實現(xiàn)更適合原生寶寶的Promise.WithResolver和LazyInit/Synchronize

開發(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')

日志如下


破費科特
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末太伊,一起剝皮案震驚了整個濱河市雇锡,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌僚焦,老刑警劉巖锰提,帶你破解...
    沈念sama閱讀 218,284評論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異芳悲,居然都是意外死亡立肘,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,115評論 3 395
  • 文/潘曉璐 我一進店門名扛,熙熙樓的掌柜王于貴愁眉苦臉地迎上來谅年,“玉大人,你說我怎么就攤上這事肮韧∪邗澹” “怎么了?”我有些...
    開封第一講書人閱讀 164,614評論 0 354
  • 文/不壞的土叔 我叫張陵弄企,是天一觀的道長超燃。 經(jīng)常有香客問我,道長拘领,這世上最難降的妖魔是什么意乓? 我笑而不...
    開封第一講書人閱讀 58,671評論 1 293
  • 正文 為了忘掉前任,我火速辦了婚禮约素,結(jié)果婚禮上洽瞬,老公的妹妹穿的比我還像新娘。我一直安慰自己业汰,他們只是感情好伙窃,可當(dāng)我...
    茶點故事閱讀 67,699評論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著样漆,像睡著了一般为障。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,562評論 1 305
  • 那天鳍怨,我揣著相機與錄音呻右,去河邊找鬼。 笑死鞋喇,一個胖子當(dāng)著我的面吹牛声滥,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播侦香,決...
    沈念sama閱讀 40,309評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼落塑,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了罐韩?” 一聲冷哼從身側(cè)響起憾赁,我...
    開封第一講書人閱讀 39,223評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎散吵,沒想到半個月后龙考,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,668評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡矾睦,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,859評論 3 336
  • 正文 我和宋清朗相戀三年晦款,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片枚冗。...
    茶點故事閱讀 39,981評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡缓溅,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出官紫,到底是詐尸還是另有隱情,我是刑警寧澤州藕,帶...
    沈念sama閱讀 35,705評論 5 347
  • 正文 年R本政府宣布束世,位于F島的核電站,受9級特大地震影響床玻,放射性物質(zhì)發(fā)生泄漏毁涉。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,310評論 3 330
  • 文/蒙蒙 一锈死、第九天 我趴在偏房一處隱蔽的房頂上張望贫堰。 院中可真熱鬧,春花似錦待牵、人聲如沸其屏。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,904評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽偎行。三九已至,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間蛤袒,已是汗流浹背熄云。 一陣腳步聲響...
    開封第一講書人閱讀 33,023評論 1 270
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留妙真,地道東北人缴允。 一個月前我還...
    沈念sama閱讀 48,146評論 3 370
  • 正文 我出身青樓,卻偏偏與公主長得像珍德,于是被迫代替她去往敵國和親练般。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 44,933評論 2 355

推薦閱讀更多精彩內(nèi)容