Promise All隊(duì)列在Canvas應(yīng)用上的小技巧

前幾天在做一個(gè)抽獎(jiǎng)轉(zhuǎn)盤的時(shí)候,突然集中用到promise api所以記錄并總結(jié)一二。

需求是做一個(gè)如下的轉(zhuǎn)盤,轉(zhuǎn)盤上的圖片和文字是從后端字段返回的。

image

文字的繪制倒是問題不大,難點(diǎn)在于圖片,眾所周知canvas的context.drawImage(img element)所繪制的圖片需要是已經(jīng)保證onload的img對(duì)象,當(dāng)時(shí)我的第一想法是拿到后端圖片數(shù)組之后依次onload它,并塞進(jìn)一個(gè)新的數(shù)組,數(shù)組長度 = 后端數(shù)組長度,再調(diào)用繪制api不就行了,偽代碼如下


const newArr = []

for (let i = 0; i <arr.length; i++) {

      arr[i].onload  = () => {

        newArr.push(arr[i])

        if (newArr.length === 后端圖片數(shù)組.length) {

              調(diào)用方法繪制轉(zhuǎn)盤方法

        }

      }

}

至少一開始我也覺得沒問題的,但是發(fā)現(xiàn)只要你清空緩存(第一次進(jìn)入)圖片順序就不對(duì)了,抽獎(jiǎng)的順序不對(duì)那可不是小事情,于是乎我console了一下如上代碼的輸出數(shù)組的圖片順序,我發(fā)現(xiàn)他并不會(huì)一個(gè)一個(gè)按照順序的塞入數(shù)組,想到for和onload的執(zhí)行原理,它onload完了才會(huì)給你這個(gè)回調(diào),那確實(shí)是不可靠的。

后來大佬看到我在糾結(jié)于此,便提出你可以參考一下我的做法隨手便甩給我一個(gè)倉庫地址,我看到第一眼promise all這個(gè)api我就知道了大概做法(也就是說其實(shí)我并沒有看大佬后面的具體實(shí)現(xiàn)2333,不過我猜想應(yīng)該差不多)。這個(gè)api第一次用還是當(dāng)時(shí)為了應(yīng)付面試所以臨時(shí)學(xué)習(xí)的,事實(shí)上工作中前端業(yè)務(wù)所用到的場景并不多,一般在后端nodejs上可能對(duì)于隊(duì)列之間有嚴(yán)格前后順序依賴關(guān)系的業(yè)務(wù)會(huì)比較有幫助,一般前端需求promise單api即可完成所以使用不多,但恰好canvas這個(gè)drawimage需要的就是加載完的圖片,而且需要順序正確。

下面是具體代碼,在preloadImage我們把img的onload這一過程作為promise對(duì)象存進(jìn)隊(duì)列,也就是說其實(shí)你打印this.renderList 會(huì)得到[promise, promise,promise,promise,....]這樣一個(gè)數(shù)組, 這個(gè)promise對(duì)象返回值就是我們已經(jīng)onload成功的img對(duì)象,再通過promise all,它等待所有返回完成再執(zhí)行后面的繪制過程,雖然這個(gè)過程可能會(huì)有一點(diǎn)點(diǎn)滯后但是對(duì)于這種強(qiáng)順序關(guān)系并且需要已經(jīng)加載完成的事件,這個(gè)api就發(fā)揮的淋漓精致了。


  async renderTheWheelImage(params) {    // params : ['圖片src', '圖片src', ....]

            for (let i = 0; i < params.length; i++) {

                await this.preloadImage(params[i])

            }

            Promise.all(this.renderList).then((res) => {

               // 繪制轉(zhuǎn)盤的方法(res)

            })

        },

        preloadImage(item) {

            this.renderList.push(new Promise((resolve, reject) => {

                const newImage = new Image()

                newImage.onload = () => {

                    resolve(newImage)

                }

                newImage.onerror = reject

                newImage.src = item

            }))

        },

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 第一部分 HTML&CSS整理答案 1. 什么是HTML5? 答:HTML5是最新的HTML標(biāo)準(zhǔn)。 注意:講述HT...
    kismetajun閱讀 28,771評(píng)論 1 45
  • 一、圖形的組合方式 globalAlpha是一個(gè)介于0和1之間的值(包括0和1),用于指定所有繪制的透明度。默認(rèn)值...
    空谷悠閱讀 1,471評(píng)論 0 0
  • $HTML, HTTP,web綜合問題 1、前端需要注意哪些SEO 2、 的title和alt有什么區(qū)別 3、HT...
    Hebborn_hb閱讀 4,761評(píng)論 0 20
  • 作者: kim先生 來源: 自創(chuàng) 今天我們講的是ES6中的Promise這個(gè)異步操作對(duì)象。在學(xué)習(xí)Promise之前...
    前端進(jìn)階體驗(yàn)閱讀 819評(píng)論 0 0
  • JS中的原型鏈機(jī)制的本質(zhì)就是對(duì)象之間的關(guān)聯(lián)關(guān)系。 面向委托的設(shè)計(jì) 我們需要把思路從類和繼承的設(shè)計(jì)模式轉(zhuǎn)換到委托行為...
    將軍肚閱讀 569評(píng)論 0 49

友情鏈接更多精彩內(nèi)容