#typescript #promise
#typescript #обещание
Вопрос:
Я хочу дождаться, что два или более обещаний будут заблокированы, пока для меня будут доступны результаты.
Поэтому я использую этот Promise.allSettled
метод. Это работает, если два обещания являются плоскими. Но если одно из этих обещаний состоит из внутренних обещаний, это не сработает.
Promise.allSettled([
report?.getActivePage(), //return a Promise object
exportVisualData("9df20366a984c945beb5")
])
.then((results) => {
results.forEach((result, index) => {
if (result.status === "rejected") {
const rejectedResult: PromiseRejectedResult =
result as PromiseRejectedResult;
console.log(rejectedResult);
} else if (result.status === "fulfilled") {
if (index === 0) {
const fulfilledResult: PromiseFulfilledResult<Page | undefined> =
result as PromiseFulfilledResult<Page | undefined>;
console.log(fulfilledResult);
fulfilledResult.value?.setActive();
} else {
const fulfilledResult: PromiseFulfilledResult<void | IExportDataResult> =
result as PromiseFulfilledResult<void | IExportDataResult>;
console.log(fulfilledResult);
}
}
});
function exportVisualData(id: string): Promise<void | IExportDataResult> {
return report!.getPages().then((pages) => {
pages.forEach((page) => {
page.getVisuals().then((visualDescriptors) =>
visualDescriptors.forEach((visualDescriptor) => {
if (visualDescriptor.name === id) {
if (!page.isActive) {
page.setActive().then((__) => {
return visualDescriptor?.exportData(
ExportDataType.Summarized
);
});
} else {
return visualDescriptor?.exportData(ExportDataType.Summarized);
}
}
})
);
});
});
Promise.allSettled не имеет результата во втором из-за внутренних обещаний, как я могу заставить это работать.
{статус: ‘выполнено’, значение: Страница} {статус: ‘выполнено’, значение: не определено}
Комментарии:
1. Я не следую вашему коду, но внутренние обещания могут отслеживаться только внешним / содержащим обещанием, если вы
return
их извлекаете из.then()
обработчика, чтобы они были связаны вместе. И вы также не можете сделать это должным образом из.forEach()
цикла, потому что возврат чего-либо из.forEach()
цикла никуда не приведет. Вероятно, вместо этого вам нужно будет перейти кfor
циклу. И, если вам нужно отслеживать все обещания в цикле, затем используйтеPromise.all()
илиPromise.allSettled()
там.2. @jfriend00 не могли бы вы, пожалуйста, написать пример с псевдокодом, я думаю, что я не могу следовать за вами на 100 процентов
3. Я пытался переписать вашу
exportVisualData()
функцию, но я не могу сказать, что вы собираетесь делать, когда делаетеreturn visualDescriptor?.exportData(ExportDataType.Summarized);
. К чему вы пытаетесь это вернуть? Вы находитесь внутри цикла, поэтому пытаетесь ли вы выйти из цикла, когда переходите к этому оператору, или вы пытаетесь накапливать результаты каждой итерации цикла? Я не понимаю, что должен делать этот код. Куда это возвращаемое значение должно идти? Куда N из них должны идти?4.
visualDescriptor?.exportData(ExportDataType.Summarized)
это метод из API Power BI (игровая площадка. powerbi.com/de-de/dev-sandbox ). В настоящее время моя цель — экспортировать данные только для одного примера visual. В конце я хочу собрать данные из разных визуальных объектов внутри одного вызова функции как часть массива. Поэтому я должен изменить ввод со строки на массив строк.5. Хорошо, итак, вам нужен плоский массив результатов с любым количеством совпадений?
Ответ №1:
Вот переписанная exportVisualData()
функция, которая собирает все результаты, соответствующие вашему visualDescriptor.name
тесту, в массив и превращает этот массив в разрешенное значение exportVisualData()
возвращаемого обещания.
Я не знал visualDescriptor?.exportData(ExportDataType.Summarized)
, возвращает ли обещание или нет. В случае, если это произойдет, я ставлю await
перед ним. Если он просто возвращает значение напрямую, вы можете удалить это await
.
Кроме того, я не знаю TypeScript, поэтому вам придется добавить информацию о типе в этот код:
async function exportVisualData(id: string): Promise < void | IExportDataResult > {
const results = [];
const pages = await report!.getPages();
for (let page of pages) {
let visualDescriptors = await page.getVisuals();
for (let visualDescriptor of visualDescriptors) {
if (visualDescriptor.name === id) {
if (!page.isActive) {
await page.setActive();
}
results.push(await visualDescriptor?.exportData(ExportDataType.Summarized));
}
}
}
return results;
}
Обратите внимание, что при этом не выполняются все эти асинхронные операции параллельно, поэтому нет необходимости использовать Promise.allSettled()
результат. Он просто возвращает одно обещание, которое преобразуется в массив значений.
Если вы хотите перехватывать ошибки и продолжать обработку в этой функции, вы можете попробовать / перехватить в каждом цикле и continue
в catch
.
Если вы хотите запускать все параллельно, это сложнее кодировать здесь из if (visualDescriptor.name === id)
-за того, что вы хотите пропустить некоторые элементы, чтобы вы не знали, сколько результатов вы ожидаете, пока не дойдете до результатов.