摘要:昨天也是好好的看了一下的源碼,今天打算自己來做一下解析。源碼如下這段代碼真的是很短,但是方法真的很巧妙。因為兩個方法用到了,這里把的源碼也貼出來源碼的描述就是為了執行而創建的。最后再次感謝提供的思路。
原文鏈接,轉載請注明出處
最近看了Ma63d關于爬蟲的這篇文章,正好自己也在做爬蟲,看到他在文中提到了co-parallel和co-gather,就打算改一下自己的代碼(本來代碼就只是為了爬一些自己感興趣的東西,現在還在改,地址在這里)。昨天也是好好的看了一下co-parallel的源碼,今天打算自己來做一下解析。
co-parallel源碼如下:
var thread = require("co-thread"); module.exports = function *parallel(thunks, n){ var n = Math.min(n || 5, thunks.length); var ret = []; var index = 0; function *next() { var i = index++; ret[i] = yield thunks[i]; if (index < thunks.length) yield next; } yield thread(next, n); return ret; };
這段代碼真的是很短,但是方法真的很巧妙。因為兩個方法用到了co-thread,這里把co-thread的源碼也貼出來:
function thread(fn, n) { var gens = []; while (n--) gens.push(fn); return gens; }
Run fn n times in parallel.
源碼的描述就是為了parallel執行而創建的。由于在next外部創建了一個index變量,通過控制index的變化就可以使得每次執行的next函數都是不同的函數,在next中繼續遞歸yield自己的話就是可以繼續執行不同的next,最終把所有的thunks都yield了一遍,方法是不是很巧妙。
如果你覺得我說的話很混亂,那我們還是還是拿一個co-parallel中的例子來講吧
var request = require("co-request"); var co = require("co"); var parallel = require("co-parallel"); var urls = [ "http://google.com", "http://yahoo.com", "http://ign.com", "http://cloudup.com", "http://myspace.com", "http://facebook.com", "http://cuteoverload.com", "http://uglyoverload.com", "http://segment.io" ]; function *status(url) { console.log("GET %s", url); var s = (yield request(url)).statusCode; return s; } co(function *(){ var start = Date.now(); var reqs = urls.map(status); var res = yield parallel(reqs, 3); console.log(res); console.log("duration: %dms", Date.now() - start); });
直接看到var reqs = urls.map(status);這句,由于傳遞給map的callback是一個Generator函數,所以最后的返回就是Generator的內部指針,也就是Iterator,也就是status()執行了一遍返回的結果。
再到var res = yield parallel(reqs, 3);這里,由于parallel是一個Generator,所以直接進入parallel中,因為n=3所以thread返回的數組內容應該是類似這個 [function*() {yield thunks[0]},function*(){yield thunks[1]}]。由于yield thread返回的結果是數組,在co中會對數組做Promise.all(obj.map(toPromise, this));因為obj中都是Generator,所以toPromise會直接對每一個Generator繼續調用co(function*(){yield thunk[i]})。在next中最后又繼續yield自己,所以當當一個thunk結束之后會繼續下一個thunk。
co-gatherco-gather實現的和co-parallel差不多的功能,只是增加了并行錯誤處理機制。因為Promise.all方法會在其中任何一個出問題的時候都把錯誤扔出來, co-gather是對all中每一個方法都做了錯誤處理,讓Promise.all方法不會拋錯,源碼如下:
var thread = require("co-thread"); module.exports = function *gather(thunks, n){ n = Math.min(n || 5, thunks.length); var ret = []; var index = 0; function *next() { var i = index++; ret[i] = {isError: false}; try { ret[i].value = yield thunks[i]; } catch (err) { ret[i].error = err; ret[i].isError = true; } if (index < thunks.length) yield next; } yield thread(next, n); return ret; };
和co-parallel不同的地方就在于對yield thunks[i]做了一層try catch,然后返回的包含執行結果的對象。
總結單單是看parallel的代碼還是很好理解的,但是由于自己co的源碼理解的不好,所以自己在捋清example的時候有點混亂了,后來又重新仔細的看了一遍了co的源碼以及阮一峰的Generator的講解,自己才弄明白。最后再次感謝Ma63d提供的思路。
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/86707.html
承繼上篇內容:下面是parseHTML 函數源碼解析 varstartTagMatch=parseStartTag(); if(startTagMatch){ handleStartTag(startTagMatch); if(shouldIgnoreFirstNewline(startTagMatch.tagName,html)){ advance(1); } co...
這是講 ahooks 源碼的第一篇文章,簡要就是以下幾點: 加深對 React hooks 的理解?! W習如何抽象自定義 hooks。構建屬于自己的 React hooks 工具庫?! ∨囵B閱讀學習源碼的習慣,工具庫是一個對源碼閱讀不錯的選擇?! ∽ⅲ罕鞠盗袑?ahooks 的源碼解析是基于v3.3.13。自己 folk 了一份源碼,主要是對源碼做了一些解讀,可見詳情。 第一篇主要介紹 a...
vue parseHTML函數解析器遇到結束標簽,在之前文章中已講述完畢?! ±缬衕tml(template)字符串: <divid="app"> <p>{{message}}</p> </div> 產出如下: { attrs:["id="app"","id...
現在我們講compileToFunctions 的使用方法,現在看看內容: //compile varcompiled=compile(template,options); 其實真正應該講的就是 compile 函數?! 〗馕?compile 上述代碼在調用 compile ,其中模板字符串 template ,就是讓選項參數 options 的第二個參數傳遞給 compile 函數...
摘要:前言源碼解析一模版渲染源碼解析二雙向綁定官網給出的如下結果源碼分析判斷參數是否包含屬性本例中本例中和是函數監聽計算屬性設置,延遲執行的方法設置可以通過本例方式訪問計算屬性對象初始化時會針對屬性的所有值分別一個對象,在源碼解析二中有詳細介 前言 1、Vue源碼解析(一)-模版渲染2、Vue源碼解析(二)-MVVM雙向綁定 demo 官網給出的demo如下 new Vue({ el...
閱讀 2993·2021-10-13 09:39
閱讀 2694·2021-09-27 13:34
閱讀 2031·2019-08-30 15:55
閱讀 3260·2019-08-30 15:43
閱讀 3631·2019-08-30 11:16
閱讀 1748·2019-08-26 18:28
閱讀 1284·2019-08-26 13:56
閱讀 915·2019-08-26 13:35