我用的是egg1.x,基于koa。然后就是各種generator,各種yield調(diào)用。這樣的好處是編碼舒服,都是同步代碼。缺點是在某些情況下,速度會異常緩慢。比如有些邏輯需要基于http協(xié)議循環(huán)調(diào)用另外的服務(wù)。egg官網(wǎng)上提供了一種基于yield的控制并發(fā)方法,代碼如下:
const [ news, user ] = yield [
ctx.service.news.list(topic),
ctx.service.user.get(uid),
];
這是一種極度簡單的使用場景。它無法控制并發(fā)量。所以我把它改造成了如下代碼:
const concurrency = 5;
let index = 0;
let tempArr = [];
for (const item of data) {
tempArr.push(ctx.service.user.get(item.uid));
if (index === concurrency) {
yield tempArr;
tempArr = [];
index = 0;
}
index++;
}
if (tempArr.length) {
yield tempArr;
}
這樣寫確實可以達到效果,當(dāng)然如果需要處理返回值,會更復(fù)雜一點。但是本人水平有限,想不出什么辦法將這個方法進行封裝。所以想問的第一個問題便是如何封裝它。
在async的文檔上找到如下代碼
async.mapLimit(urls, 5, async function(url) {
const response = await fetch(url)
return response.body
}, (err, results) => {
if (err) throw err
// results is now an array of the response bodies
console.log(results)
})
這不就是我夢寐以求的嗎?然而無情的現(xiàn)實是公司目前并不想升級nodejs,所以還是得乖乖用generator。后來我又想把上面的代碼改造成generator/yield
async.mapLimit(urls, 5, function* (url) {
const response = yield fetch(url)
return response.body
}, (err, results) => {
if (err) throw err
// results is now an array of the response bodies
console.log(results)
})
然而一個回調(diào)函數(shù)都執(zhí)行不了。所以第二個問題是為啥不能直接改造呢,async不是generator的語法糖嗎?
async是generator的語法糖,但不是簡單的替換就可以解決的
使用await語法自帶執(zhí)行器,而generator則是不帶執(zhí)行器,需要自己手工添加
await需要后面的變量是一個promise對象
給你個generator+promise對 async/await的實現(xiàn)
//一個generator執(zhí)行器的實現(xiàn)
function run(generator){
var gen=generator();
var resultValue=gen.next();
if(resultValue.done){
return resultValue.value;
}
function runGenerator(value){
Promise.resolve(value).then(function(data){
var resultValue=gen.next(data);
if(!resultValue.done){
runGenerator(resultValue.value);
}
}).catch(function(error){
gen.throw(new Error(error));
});
}
return runGenerator(resultValue.value);
}
//執(zhí)行執(zhí)行器,
//傳入一個generator函數(shù),yield后面帶一個promise對象
run(function *(){
var task1=function(){
return new Promise(function(resolve,reject){
setTimeout(function(){
console.log("1000");
resolve("1000");
},1000);
});
};
var task2=function(data){
return new Promise(function(resolve,reject){
setTimeout(function(){
console.log("2000 :: "+data+"");
resolve("2000 :: "+data+"");
},1000);
});
};
try{
var data=yield task1();
var data2=yield task2(data);
return data2;
}catch(error){
console.log("~~~~error~~~");
}
});第一個問題:
co-parallel
第二個問題:
你需要把 function*(url){} 用 co 包一下。generator 并不會自動執(zhí)行,某種程度上你可以把 async 函數(shù)視為自動幫你 co 一下了的 generator。
但是不確定你這么寫能不能執(zhí)行,待會測試一下。
const co = require('co');
function mapLimit(urls, limit, genFn, cb) {
co(function* () {
let results = [];
while(urls.length) {
let res = yield urls.splice(0, limit).map(genFn);
results.push(...res);
}
return results;
}).then(function(res) {
cb(null, res)
}).catch(cb)
}
這樣封裝樓主看看能嗎
async.mapLimit官方文檔里要求傳asyncFUnction函數(shù),傳Generator肯定不行了
北大青鳥APTECH成立于1999年。依托北京大學(xué)優(yōu)質(zhì)雄厚的教育資源和背景,秉承“教育改變生活”的發(fā)展理念,致力于培養(yǎng)中國IT技能型緊缺人才,是大數(shù)據(jù)專業(yè)的國家
達內(nèi)教育集團成立于2002年,是一家由留學(xué)海歸創(chuàng)辦的高端職業(yè)教育培訓(xùn)機構(gòu),是中國一站式人才培養(yǎng)平臺、一站式人才輸送平臺。2014年4月3日在美國成功上市,融資1
北大課工場是北京大學(xué)校辦產(chǎn)業(yè)為響應(yīng)國家深化產(chǎn)教融合/校企合作的政策,積極推進“中國制造2025”,實現(xiàn)中華民族偉大復(fù)興的升級產(chǎn)業(yè)鏈。利用北京大學(xué)優(yōu)質(zhì)教育資源及背
博為峰,中國職業(yè)人才培訓(xùn)領(lǐng)域的先行者
曾工作于聯(lián)想擔(dān)任系統(tǒng)開發(fā)工程師,曾在博彥科技股份有限公司擔(dān)任項目經(jīng)理從事移動互聯(lián)網(wǎng)管理及研發(fā)工作,曾創(chuàng)辦藍(lán)懿科技有限責(zé)任公司從事總經(jīng)理職務(wù)負(fù)責(zé)iOS教學(xué)及管理工作。
浪潮集團項目經(jīng)理。精通Java與.NET 技術(shù), 熟練的跨平臺面向?qū)ο箝_發(fā)經(jīng)驗,技術(shù)功底深厚。 授課風(fēng)格 授課風(fēng)格清新自然、條理清晰、主次分明、重點難點突出、引人入勝。
精通HTML5和CSS3;Javascript及主流js庫,具有快速界面開發(fā)的能力,對瀏覽器兼容性、前端性能優(yōu)化等有深入理解。精通網(wǎng)頁制作和網(wǎng)頁游戲開發(fā)。
具有10 年的Java 企業(yè)應(yīng)用開發(fā)經(jīng)驗。曾經(jīng)歷任德國Software AG 技術(shù)顧問,美國Dachieve 系統(tǒng)架構(gòu)師,美國AngelEngineers Inc. 系統(tǒng)架構(gòu)師。