成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專欄INFORMATION COLUMN

小程序圖片合成:異步并發(fā)渲染→同步阻塞渲染

zhoutao / 1535人閱讀

摘要:故事開始了,小程序圖片合成真機測試時,會報錯。所以只能將異步并發(fā)改為同步阻塞式渲染。

故事開始了,小程序canvas圖片合成 真機測試時,會報錯:getImageInfo failed 。
也就是說,我這邊異步請求50張圖片,每張圖片都是通過getImageInfo下載到本地并且繪制到canvas畫布上,但是在處理的過程中,getImageInfo會出現(xiàn)獲取本地圖片錯誤的情況,也就是說請求50張,最后繪制出來的可能只有45張或者40張,非常明顯的數(shù)據(jù)丟失,要比數(shù)據(jù)包丟包嚴重N倍。

經(jīng)過一系列排查后,發(fā)現(xiàn)可能原因有2個:
1.圖片請求的域名必須是小程序經(jīng)過小程序驗證的(大佬們通過換域名跳轉(zhuǎn)解決了這個風險)
2.小程序的請求并發(fā)數(shù)超過小程序的最大并發(fā)限制, request、uploadFile、downloadFile 的最大并發(fā)限制是 10 個

開發(fā)者經(jīng)驗:
"代碼問題,小程序同時只能發(fā)送10個網(wǎng)絡(luò)請求,超過后就會報錯。圖片信息獲取也占用這10個網(wǎng)絡(luò)請求。要把圖片信息獲取序列化。控制在同一個時間內(nèi)段內(nèi)不超10個請求,我是做了隊列處理,一次只發(fā)送一個請求。完成后在走下一個"

CNODE社區(qū)經(jīng)驗
原生promise、async怎么實現(xiàn)控制并發(fā)數(shù)量
1. bluebird可以做到控制并發(fā)數(shù)量。
2.用?for?遍歷,然后一次拿2個,或者多個出來?再?Promise.all?之后?再?await
3.promise.map包
const promise = pmap(arr, async item => {
? ? ?? //
}, 10) // 最后是 concurrency
4. 不想用庫,那就把 https://github.com/sindresorh...?對應(yīng)的方法,CTRL+C?過來唄

bluebird并發(fā)控制數(shù)量...并沒有接觸過,但是感覺底層都是async和await。

需要去溫習下async和await了

async是什么?
async函數(shù)聲明定義了一個異步函數(shù),這個函數(shù)返回一個AsyncFunction對象。

async function name([param,[param[,...param]]]){

? ? ?statements

}

函數(shù)都有return的東西,async return的是什么,它返回的是AsyncFunction對象,表示執(zhí)行包含在函數(shù)中的代碼的異步函數(shù),與new一個Object或者自己寫的類一樣,new AsyncFunction([arg1[, arg2[, ...argN]],] functionBody)

await是什么?

await操作符被用來等待一個Promise對象。它僅僅在async函數(shù)中使用。
[rv] = await expression;

說得形象些,async許下承諾,await接收承諾。
async許下了什么,許下一個承諾函數(shù),也就是一個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()執(zhí)行
打印"calling"
resolveAfter2Seconds() 執(zhí)行,Promise對象執(zhí)行中
與此同時,await做好了接收Promise對象的準備
2秒后,await接收到Promise,賦值給result
打印"resolved"

溫習結(jié)束,開始嘗試異步控制的辦法。

網(wǎng)友的代碼只言片語,實在看不懂,到官網(wǎng)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.

懵逼,看完并不會用。

但是經(jīng)過一番折騰,終于會用了,和Array.prototype.map有點類似的,只不過Promise.map傳入的callback是一個AsyncFunction,也就是返回一個Promise的函數(shù)。

做到了并發(fā)數(shù)的控制,但是控制并發(fā)數(shù)以后圖片數(shù)據(jù)還是獲取不完整,10個并發(fā),9個并發(fā),5個并發(fā),2個并發(fā),都試過了,都是不行。必須改異步為同步,也就是限制每次只能請求1個,也就是并發(fā)數(shù)設(shè)置為1即可,但是用戶體驗上非常不好,用戶只能看到一張一張圖片,假設(shè)有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方法控制并發(fā)請求數(shù)實現(xiàn)的,也就是 { concurrency: 1}這里,但是沒有達到預(yù)期小于10個并發(fā)的處理預(yù)期,因為只要是并發(fā),都會造成數(shù)據(jù)丟失。

所以只能將異步并發(fā)改為同步阻塞式渲染。

這個問題的出現(xiàn)與我們圖片合成功能的設(shè)計架構(gòu)有很大的問題,其實最理想的情況是,服務(wù)端直接返回一張完整的大圖片,前端僅需一次網(wǎng)絡(luò)請求即可,不存在同步異步這種令人頭疼的問題。

雖然最后通過異步并發(fā)渲染轉(zhuǎn)換為同步阻塞渲染,獲取到了全部的圖片資源,但是這并不是好的解決方案,所以這篇文章的主要是講了一個異步并發(fā)數(shù)量控制的方法,也穿插著加入了一些異步并發(fā)渲染與同步阻塞渲染對比的內(nèi)容,還要就是我對圖片合成這個功能設(shè)計架構(gòu)上的一些想法。

That"s it !

文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請注明本文地址:http://systransis.cn/yun/107208.html

相關(guān)文章

  • web前端性能優(yōu)化總結(jié)

    摘要:但是還是會阻塞事件,所以會可能在觸發(fā)前或后執(zhí)行,但是一定會在事件前觸發(fā)。當監(jiān)聽到該圖片元素進入可視窗口時,即將自定義屬性中的地址存儲到屬性中,達到懶加載的效果。當代碼執(zhí)行,線程被凍結(jié)。所以的性能讓變慢。 概括 涉及到的分類 網(wǎng)絡(luò)層面 構(gòu)建層面 瀏覽器渲染層面 服務(wù)端層面 涉及到的功能點 資源的合并與壓縮 圖片編解碼原理和類型選擇 瀏覽器渲染機制 懶加載預(yù)加載 瀏覽器存儲 緩存機制...

    evin2016 評論0 收藏0
  • WEB/H5性能優(yōu)化總結(jié)

    摘要:如下圖所示一重繪與回流前端性能優(yōu)化最關(guān)鍵的就是減少頁面的重繪與回流。很明顯就是少了一步,這是因為把會觸發(fā)回流的屬性用替代,這樣就使渲染的過程減少了這一步,使渲染的時間減少從而提高性能。 我們今天來說說前端圖形渲染優(yōu)化,因為我接下來的時間可能要開始研究webgl方面的東西,所以就在這里把之前做過的H5做一個總結(jié),現(xiàn)同步發(fā)布于GERRY_BLOG,TiMiGerry-知乎,轉(zhuǎn)載請保留鏈接。...

    stdying 評論0 收藏0
  • WEB/H5性能優(yōu)化總結(jié)

    摘要:如下圖所示一重繪與回流前端性能優(yōu)化最關(guān)鍵的就是減少頁面的重繪與回流。很明顯就是少了一步,這是因為把會觸發(fā)回流的屬性用替代,這樣就使渲染的過程減少了這一步,使渲染的時間減少從而提高性能。 我們今天來說說前端圖形渲染優(yōu)化,因為我接下來的時間可能要開始研究webgl方面的東西,所以就在這里把之前做過的H5做一個總結(jié),現(xiàn)同步發(fā)布于GERRY_BLOG,TiMiGerry-知乎,轉(zhuǎn)載請保留鏈接。...

    mingde 評論0 收藏0
  • 瀏覽器知識

    摘要:瀏覽器的渲染進程是多線程的。異步請求線程在在連接后是通過瀏覽器新開一個線程請求將檢測到狀態(tài)變更時,如果設(shè)置有回調(diào)函數(shù),異步線程就產(chǎn)生狀態(tài)變更事件,將這個回調(diào)再放入事件隊列中。 [TOC] 瀏覽器進程線程 區(qū)分線程和進程 **- 什么是進程** 狹義定義:進程是正在運行的程序的實例(an instance of a computer program that is being exe...

    Pluser 評論0 收藏0

發(fā)表評論

0條評論

zhoutao

|高級講師

TA的文章

閱讀更多
最新活動
閱讀需要支付1元查看
<