摘要:故事開始了,小程序圖片合成真機測試時,會報錯。所以只能將異步并發改為同步阻塞式渲染。
故事開始了,小程序canvas圖片合成 真機測試時,會報錯:getImageInfo failed 。
也就是說,我這邊異步請求50張圖片,每張圖片都是通過getImageInfo下載到本地并且繪制到canvas畫布上,但是在處理的過程中,getImageInfo會出現獲取本地圖片錯誤的情況,也就是說請求50張,最后繪制出來的可能只有45張或者40張,非常明顯的數據丟失,要比數據包丟包嚴重N倍。
經過一系列排查后,發現可能原因有2個:
1.圖片請求的域名必須是小程序經過小程序驗證的(大佬們通過換域名跳轉解決了這個風險)
2.小程序的請求并發數超過小程序的最大并發限制, request、uploadFile、downloadFile 的最大并發限制是 10 個
開發者經驗:
"代碼問題,小程序同時只能發送10個網絡請求,超過后就會報錯。圖片信息獲取也占用這10個網絡請求。要把圖片信息獲取序列化。控制在同一個時間內段內不超10個請求,我是做了隊列處理,一次只發送一個請求。完成后在走下一個"
CNODE社區經驗
原生promise、async怎么實現控制并發數量
1. bluebird可以做到控制并發數量。
2.用?for?遍歷,然后一次拿2個,或者多個出來?再?Promise.all?之后?再?await
3.promise.map包
const promise = pmap(arr, async item => {
? ? ?? //
}, 10) // 最后是 concurrency
4. 不想用庫,那就把 https://github.com/sindresorh...?對應的方法,CTRL+C?過來唄
bluebird并發控制數量...并沒有接觸過,但是感覺底層都是async和await。
需要去溫習下async和await了
async是什么?
async函數聲明定義了一個異步函數,這個函數返回一個AsyncFunction對象。
async function name([param,[param[,...param]]]){ ? ? ?statements }
函數都有return的東西,async return的是什么,它返回的是AsyncFunction對象,表示執行包含在函數中的代碼的異步函數,與new一個Object或者自己寫的類一樣,new AsyncFunction([arg1[, arg2[, ...argN]],] functionBody)
await是什么?
await操作符被用來等待一個Promise對象。它僅僅在async函數中使用。
[rv] = await expression;
說得形象些,async許下承諾,await接收承諾。
async許下了什么,許下一個承諾函數,也就是一個Promise。
await在等待什么,它在等待一個承諾,也就是一個Promise。
function resolveAfter2Seconds() { ? return new Promise(resolve => { ? setTimeout(() => { ? resolve("resolved"); ? }, 2000); ? }); } async function asyncCall() { ? console.log("calling"); ? var result = await resolveAfter2Seconds(); ? console.log(result); ? // expected output: "resolved" } asyncCall();
?=>"calling"http://瞬間打印
?=>"resolved"http://兩秒后打印
分下下上面代碼的工作原理:
asyncCall()執行
打印"calling"
resolveAfter2Seconds() 執行,Promise對象執行中
與此同時,await做好了接收Promise對象的準備
2秒后,await接收到Promise,賦值給result
打印"resolved"
溫習結束,開始嘗試異步控制的辦法。
網友的代碼只言片語,實在看不懂,到官網Promise.map來看下。
Promise.map( `? ? Iterable|Promise >?input, ? ? function(any?item,?int?index,?int?length)?mapper, ? ? [Object?{concurrency:?int=Infinity}?options]` )?->?Promise `var?promises?=?[]; for?(var?i?=?0;?i? Map Option: concurrency
You may optionally specify a concurrency limit:
...map(..., {concurrency: 3});
The concurrency limit applies to Promises returned by the mapper function and it basically limits the number of Promises created. For example, if concurrency is 3 and the mapper callback has been called enough so that there are three returned Promises currently pending, no further callbacks are called until one of the pending Promises resolves. So the mapper function will be called three times and it will be called again only after at least one of the Promises resolves.懵逼,看完并不會用。
但是經過一番折騰,終于會用了,和Array.prototype.map有點類似的,只不過Promise.map傳入的callback是一個AsyncFunction,也就是返回一個Promise的函數。
做到了并發數的控制,但是控制并發數以后圖片數據還是獲取不完整,10個并發,9個并發,5個并發,2個并發,都試過了,都是不行。必須改異步為同步,也就是限制每次只能請求1個,也就是并發數設置為1即可,但是用戶體驗上非常不好,用戶只能看到一張一張圖片,假設有60張,需要一張一張去請求,最后再合成一張完整的圖片。
但是為了保證所有圖片都能下載下來,能夠正常顯示所有的圖片,這是目前唯一的辦法。
Promise.map(photoData, function (photo) { return getImageInfoPromisified({ src: photo.url }).then(function (res) { imagesArr.push(res.path); picx = (photo.left / 2) * ratio; picy = ((photo.top - 360) / 2) * ratio; picwidth = ((photo.width / 2) - 4) * ratio; picheight = ((photo.height / 2) - 4) * ratio; ctx.drawImage(res.path, picx, picy, picwidth, picheight); ctx.draw(true); }).catch(function () { console.error("get location failed") }); }, { concurrency: 1}).then(function () { wx.canvasToTempFilePath({ canvasId: "pic", success: function (res) { console.log(res.tempFilePath) that.setData({ onlineImage: res.tempFilePath, canvasDisplay: "none" }) } }) });所有這個問題最后還是使用bluebird的promise.map方法控制并發請求數實現的,也就是 { concurrency: 1}這里,但是沒有達到預期小于10個并發的處理預期,因為只要是并發,都會造成數據丟失。
所以只能將異步并發改為同步阻塞式渲染。
這個問題的出現與我們圖片合成功能的設計架構有很大的問題,其實最理想的情況是,服務端直接返回一張完整的大圖片,前端僅需一次網絡請求即可,不存在同步異步這種令人頭疼的問題。
雖然最后通過異步并發渲染轉換為同步阻塞渲染,獲取到了全部的圖片資源,但是這并不是好的解決方案,所以這篇文章的主要是講了一個異步并發數量控制的方法,也穿插著加入了一些異步并發渲染與同步阻塞渲染對比的內容,還要就是我對圖片合成這個功能設計架構上的一些想法。
That"s it !
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/107208.html
摘要:但是還是會阻塞事件,所以會可能在觸發前或后執行,但是一定會在事件前觸發。當監聽到該圖片元素進入可視窗口時,即將自定義屬性中的地址存儲到屬性中,達到懶加載的效果。當代碼執行,線程被凍結。所以的性能讓變慢。 概括 涉及到的分類 網絡層面 構建層面 瀏覽器渲染層面 服務端層面 涉及到的功能點 資源的合并與壓縮 圖片編解碼原理和類型選擇 瀏覽器渲染機制 懶加載預加載 瀏覽器存儲 緩存機制...
摘要:如下圖所示一重繪與回流前端性能優化最關鍵的就是減少頁面的重繪與回流。很明顯就是少了一步,這是因為把會觸發回流的屬性用替代,這樣就使渲染的過程減少了這一步,使渲染的時間減少從而提高性能。 我們今天來說說前端圖形渲染優化,因為我接下來的時間可能要開始研究webgl方面的東西,所以就在這里把之前做過的H5做一個總結,現同步發布于GERRY_BLOG,TiMiGerry-知乎,轉載請保留鏈接。...
摘要:如下圖所示一重繪與回流前端性能優化最關鍵的就是減少頁面的重繪與回流。很明顯就是少了一步,這是因為把會觸發回流的屬性用替代,這樣就使渲染的過程減少了這一步,使渲染的時間減少從而提高性能。 我們今天來說說前端圖形渲染優化,因為我接下來的時間可能要開始研究webgl方面的東西,所以就在這里把之前做過的H5做一個總結,現同步發布于GERRY_BLOG,TiMiGerry-知乎,轉載請保留鏈接。...
閱讀 1660·2021-09-28 09:35
閱讀 1131·2019-08-30 15:54
閱讀 1656·2019-08-30 15:44
閱讀 3363·2019-08-30 14:09
閱讀 488·2019-08-29 14:05
閱讀 2661·2019-08-28 17:53
閱讀 1978·2019-08-26 13:41
閱讀 1710·2019-08-26 13:26