3 回答

TA貢獻(xiàn)1111條經(jīng)驗(yàn) 獲得超0個(gè)贊
我將轉(zhuǎn)換dynamoClient.scan為基于 Promise 的函數(shù),然后await每次調(diào)用它,例如:
const dynamoClientScanProm = (params) => new Promise((resolve, reject) => {
dynamoClient.scan(params, function (err, data) {
if (err) reject(err);
else resolve(data);
});
});
// ...
// in an async function:
try {
await dynamoClientScanProm(productParams);
await dynamoClientScanProm(couponsParams);
await dynamoClientScanProm(retailerParams);
// promisify/await this too, if it's asynchronous
ses.sendTemplatedEmail(email);
} catch(e) {
// handle errors
}
目前還不清楚是否需要使用調(diào)用的結(jié)果,但是如果確實(shí)需要結(jié)果并且不只是需要等待 Promise 解析,則在awaiting時(shí)賦值給一個(gè)變量,例如
const productResults = await dynamoClientScanProm(productParams);
也就是說,如果 的其他調(diào)用沒有使用結(jié)果dynamoClientScanProm,那么并行(使用Promise.all)而不是串行運(yùn)行所有調(diào)用會(huì)更有意義,這樣可以更快地完成整個(gè)過程。

TA貢獻(xiàn)1818條經(jīng)驗(yàn) 獲得超7個(gè)贊
回答:
您可以使用Symbol.iterator根據(jù)for await來異步執(zhí)行您的承諾。這可以打包成一個(gè)構(gòu)造函數(shù),在這個(gè)例子中它被調(diào)用Serial(因?yàn)槲覀冋谝粋€(gè)一個(gè)地通過 promises,按順序)
function Serial(promises = []) {
return {
promises,
resolved: [],
addPromise: function(fn) {
promises.push(fn);
},
resolve: async function(cb = i => i, err = (e) => console.log("trace: Serial.resolve " + e)) {
try {
for await (let p of this[Symbol.iterator]()) {}
return this.resolved.map(cb);
} catch (e) {
err(e);
}
},
[Symbol.iterator]: async function*() {
this.resolved = [];
for (let promise of this.promises) {
let p = await promise().catch(e => console.log("trace: Serial[Symbol.iterator] ::" + e));
this.resolved.push(p);
yield p;
}
}
}
}
以上是什么?
這是一個(gè)名為
Serial
.它將返回 Promise 的函數(shù)數(shù)組作為參數(shù)。
函數(shù)存儲(chǔ)在
Serial.promises
它存儲(chǔ)了一個(gè)空數(shù)組
Serial.resolved
- 這將存儲(chǔ)已解決的承諾請(qǐng)求。它有兩種方法:
addPromise
: 接受一個(gè)返回 Promise 的函數(shù)并將其添加到Serial.promises
resolve
:異步調(diào)用自定義Symbol.iterator
. 這iterator
會(huì)遍歷每一個(gè) promise,等待它完成,然后將它添加到Serial.resolved
. 完成后,它返回一個(gè)映射函數(shù),該函數(shù)作用于填充的Serial.resolved
數(shù)組。這使您可以簡單地調(diào)用resolve
,然后提供對(duì)響應(yīng)中成員的處理方式的回調(diào)。如果您將承諾返回給該函數(shù),則可以傳遞一個(gè)then
函數(shù)以獲取整個(gè)數(shù)組。
一個(gè)例子:
promises.resolve((resolved_request) => {
//do something with each resolved request
return resolved_request;
}).then((all_resolved_requests) => {
// do something with all resolved requests
});
下面的例子展示了如何使用它來產(chǎn)生巨大的效果,無論你是希望在每個(gè)單獨(dú)的分辨率上發(fā)生一些事情,還是等到一切都完成。
請(qǐng)注意,它們將始終按順序排列。這可以從第一個(gè)計(jì)時(shí)器設(shè)置為最高ms計(jì)數(shù)的事實(shí)中看出。第二個(gè)承諾不會(huì)甚至開始,直到第一個(gè)已完成,第三不會(huì)在第二飾面等之前開始
這讓我想到了一個(gè)重要的點(diǎn)。盡管按順序序列化您的 Promise 是有效的,但重要的是要意識(shí)到,如果它們占用任何一個(gè)需要任何時(shí)間,這將延遲您對(duì)數(shù)據(jù)的響應(yīng)。Parallel 的美妙之處在于,如果一切順利,所有請(qǐng)求都需要更短的時(shí)間來完成。如果應(yīng)用程序有多個(gè)必需的請(qǐng)求,那么像序列化這樣的東西非常有用,如果一個(gè)請(qǐng)求不可用,或者一個(gè)項(xiàng)目依賴另一個(gè)(很常見),整個(gè)事情就會(huì)失敗。
//helpers
let log = console.log.bind(console),
promises = Serial(),
timer = (tag, ms) => () => new Promise(res => {
setTimeout(() => {
res("finished " + tag);
}, ms) });
function Serial(promises = []) {
return {
promises,
resolved: [],
addPromise: function(fn) {
promises.push(fn);
},
resolve: async function(cb = i => i, err = (e) => console.log("trace: Serial.resolve " + e)) {
try {
for await (let p of this[Symbol.iterator]()) {}
return this.resolved.map(cb);
} catch (e) {
err(e);
}
},
[Symbol.iterator]: async function*() {
this.resolved = [];
for (let promise of this.promises) {
let p = await promise().catch(e => console.log("trace: Serial[Symbol.iterator] ::" + e));
this.resolved.push(p);
yield p;
}
}
}
}
promises.addPromise(timer(1, 3000));
promises.addPromise(timer(2, 1000));
promises.addPromise(timer(3, 2000));
promises
.resolve(msg => ( log(msg), msg) )
.then((complete) => log("everything is complete: " + complete));
它是如何工作的?
通過使用一個(gè)一個(gè)一個(gè)地調(diào)用每promise一個(gè)的迭代器,我們可以確定它們是按順序接收的。
雖然很多人沒有意識(shí)到這一點(diǎn)Symbol.iterator是很多比標(biāo)準(zhǔn)更強(qiáng)大的for循環(huán)。這有兩個(gè)重要原因。
第一個(gè)原因,也是適用于這種情況的原因,是因?yàn)樗试S異步調(diào)用會(huì)影響應(yīng)用對(duì)象的狀態(tài)。
第二個(gè)原因是它可以用于提供來自同一對(duì)象的兩種不同類型的數(shù)據(jù)。Ae 您可能有一個(gè)要讀取其內(nèi)容的數(shù)組:
let arr = [1,2,3,4];
您可以使用for循環(huán)或forEach獲取數(shù)據(jù):
arr.forEach(v => console.log(v));
// 1, 2, 3, 4
但是如果你調(diào)整迭代器:
arr[Symbol.iterator] = function* () {
yield* this.map(v => v+1);
};
你得到這個(gè):
arr.forEach(v => console.log(v));
// 1, 2, 3, 4
for(let v of arr) console.log(v);
// 2, 3, 4, 5
這對(duì)于許多不同的原因都很有用,包括時(shí)間戳請(qǐng)求/映射引用等。如果您想了解更多信息,請(qǐng)查看 ECMAScript 文檔:For in 和 For Of 語句
用:
它可以通過使用返回 Promise 的函數(shù)數(shù)組調(diào)用構(gòu)造函數(shù)來使用。您還可以通過使用向?qū)ο筇砑雍瘮?shù)承諾
new Serial([])
.addPromise(() => fetch(url))
在您使用該.resolve方法之前,它不會(huì)運(yùn)行函數(shù)承諾。
這意味著您可以在對(duì)異步調(diào)用執(zhí)行任何操作之前,根據(jù)需要添加臨時(shí)承諾。Ae 這兩個(gè)是一樣的:
使用 addPromise:
let promises = new Serial([() => fetch(url), () => fetch(url2), () => fetch(url3)]);
promises.addPromise(() => fetch(url4));
promises.resolve().then((responses) => responses)
沒有添加承諾:
let promises = new Serial([() => fetch(url), () => fetch(url2), () => fetch(url3), () => fetch(url4)])
.resolve().then((responses) => responses)
調(diào)整您的代碼:
以下是調(diào)整代碼以按順序執(zhí)行操作的示例。問題是,您并沒有真正提供大量的入門代碼,因此我將您的scan函數(shù)替換為timer我在之前示例中使用的函數(shù)。
要使用您的代碼實(shí)現(xiàn)此功能,您所要做的就是從您的scan函數(shù)返回一個(gè) Promise ,它會(huì)完美運(yùn)行:)
function Serial(promises = []) {
return {
promises,
resolved: [],
addPromise: function(fn) {
promises.push(fn);
},
resolve: async function(cb = i => i, err = (e) => console.log("trace: Serial.resolve " + e)) {
try {
for await (let p of this[Symbol.iterator]()) {}
return this.resolved.map(cb);
} catch (e) {
err(e);
}
},
[Symbol.iterator]: async function*() {
this.resolved = [];
for (let promise of this.promises) {
let p = await promise().catch(e => console.log("trace: Serial[Symbol.iterator] ::" + e));
this.resolved.push(p);
yield p;
}
}
}
}
const timer = (tag, ms) => new Promise(res => {
setTimeout(() => {
res("finished " + tag);
}, ms)
});
function scanProducts() {
return timer("products", 3000);
}
function scanCoupons() {
return timer("coupons", 1000);
}
async function scanRetailers() {
return timer("retailers", 2500);
}
function sendEmail(ses) {
var email = {
"Source": "test@gmail.com",
"Template": "test-template",
"Destination": {
"ToAddresses": ["test@gmail.com"]
},
"TemplateData": `{}`
}
ses.sendTemplatedEmail(email);
}
let promises = Serial([scanProducts, scanCoupons, scanRetailers]);
promises.resolve().then(resolutions => console.log(resolutions));

TA貢獻(xiàn)1779條經(jīng)驗(yàn) 獲得超6個(gè)贊
使用異步系列。它按順序運(yùn)行一系列回調(diào),盡可能簡單。
series([
function(done) {
console.log('first thing')
done()
},
function(done) {
console.log('second thing')
done(new Error('another thing'))
},
function(done) {
// never happens, because "second thing"
// passed an error to the done() callback
}
], function(err) {
console.log(err.message) // "another thing"
})
添加回答
舉報(bào)