我在寫一個(gè)后臺(tái),封裝了兩個(gè)方法去查詢數(shù)據(jù)庫,它們的返回都是Promise,調(diào)用它們都有正確的結(jié)果。
function list(req, res, next) {
let start = req.query.start;
let count = req.query.count;
exchangeDb.queryList(start, count).then(results => {
res.json(results)
}).catch(err => {
throw err;
});
}
function load(req, res, next, name) {
let limit = req.query.limit;
exchangeDb.queryVolume(name, limit).then(results => {
req.results = util.convert(results);
return next();
}).catch(err => {
throw err;
});
}
第一個(gè)返回的是列表,第二個(gè)是返回詳情。我想把它們合為一個(gè)方法,嘗試這樣做:
function list(req, res, next) {
let start = req.query.start;
let count = req.query.count;
exchangeDb.queryList(start, count).then(results => {
results.forEach((index,element) => {
exchangeDb.queryVolume(element.name,50).then(volume => {
element.volume = volume;
results[index] = element;
})
});
res.json(results)
}).catch(err => {
throw err;
});
}
顯然,它不能工作,我被這個(gè)問題深深的困擾了,如果是鏈?zhǔn)降腜romise,then().then()看上去也不能解決這個(gè)問題,請大家?guī)兔匆幌?,謝謝。
你的目的是在所有queryVolume都返回結(jié)果后,再返回json,因此res.json()一定是一個(gè)異步行為。
兩個(gè)方案:
1.在每個(gè)then里面判斷是否全部請求完畢
results.forEach((index,element) => {
const NOT_FILL = '__not_fill'
// 生成一個(gè)等長數(shù)組,打標(biāo)記
const jsonResult = new Array(results.length)
jsonResult.fill(NOT_FILL)
exchangeDb.queryVolume(element.name,50).then(volume => {
element.volume = volume;
jsonResult[index] = element;
// 數(shù)組全部有值再返回
if(!jsonResult.some(element => element === NOT_FILL)){
res.json(jsonResult)
}
})
});
2.把循環(huán)queryVolume的過程封裝成一個(gè)新的promise,resolve的條件同1的res.json,然后在這個(gè)promise的then方法中返回json
看起來你是想先取集合,再取集合中每個(gè)元素的詳情。這個(gè)時(shí)候,由于取詳情的操作也是異步操作,所以你不能直接用 forEach,通常來說,你有 Promise.all 和連接成隊(duì)列兩種做法。
Promise.all
exchangeDb.queryList(start, count)
.then(results => {
return Promise.all(results.map(element => {
return exchangeDb.queryVolume(element.name, 50);
}));
})
.then(results => {
console.log(results); // <- 這里應(yīng)該是全部詳情數(shù)據(jù)了
})
.catch(err => {
throw err;
});
如果并發(fā)壓力大的話,也可以用隊(duì)列:
exchangeDb.queryList(start, count)
.then(results => {
const all = [];
const p = results.reduce((p, element) => {
return p.then(() => {
return exchangeDb.queryVolume(element.name, 50)
.then(detail => {
all.push(detail);
});
});
}, Promise.resolve());
return all;
})
.then(results => {
console.log(results); // <- 這里應(yīng)該是全部詳情數(shù)據(jù)了
})
.catch(err => {
throw err;
});
我之前做過一次講堂:Promise 的 N 種用法,對 Promise 的講解比較詳細(xì),尤其介紹過幾種隊(duì)列的方式,建議你看一下。
北大青鳥APTECH成立于1999年。依托北京大學(xué)優(yōu)質(zhì)雄厚的教育資源和背景,秉承“教育改變生活”的發(fā)展理念,致力于培養(yǎng)中國IT技能型緊缺人才,是大數(shù)據(jù)專業(yè)的國家
達(dá)內(nèi)教育集團(tuán)成立于2002年,是一家由留學(xué)海歸創(chuàng)辦的高端職業(yè)教育培訓(xùn)機(jī)構(gòu),是中國一站式人才培養(yǎng)平臺(tái)、一站式人才輸送平臺(tái)。2014年4月3日在美國成功上市,融資1
北大課工場是北京大學(xué)校辦產(chǎn)業(yè)為響應(yīng)國家深化產(chǎn)教融合/校企合作的政策,積極推進(jìn)“中國制造2025”,實(shí)現(xiàn)中華民族偉大復(fù)興的升級產(chǎn)業(yè)鏈。利用北京大學(xué)優(yōu)質(zhì)教育資源及背
博為峰,中國職業(yè)人才培訓(xùn)領(lǐng)域的先行者
曾工作于聯(lián)想擔(dān)任系統(tǒng)開發(fā)工程師,曾在博彥科技股份有限公司擔(dān)任項(xiàng)目經(jīng)理從事移動(dòng)互聯(lián)網(wǎng)管理及研發(fā)工作,曾創(chuàng)辦藍(lán)懿科技有限責(zé)任公司從事總經(jīng)理職務(wù)負(fù)責(zé)iOS教學(xué)及管理工作。
浪潮集團(tuán)項(xiàng)目經(jīng)理。精通Java與.NET 技術(shù), 熟練的跨平臺(tái)面向?qū)ο箝_發(fā)經(jīng)驗(yàn),技術(shù)功底深厚。 授課風(fēng)格 授課風(fēng)格清新自然、條理清晰、主次分明、重點(diǎn)難點(diǎn)突出、引人入勝。
精通HTML5和CSS3;Javascript及主流js庫,具有快速界面開發(fā)的能力,對瀏覽器兼容性、前端性能優(yōu)化等有深入理解。精通網(wǎng)頁制作和網(wǎng)頁游戲開發(fā)。
具有10 年的Java 企業(yè)應(yīng)用開發(fā)經(jīng)驗(yàn)。曾經(jīng)歷任德國Software AG 技術(shù)顧問,美國Dachieve 系統(tǒng)架構(gòu)師,美國AngelEngineers Inc. 系統(tǒng)架構(gòu)師。