typescript 打字稿 - 在函数返回之前等待承诺解决
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/49906865/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Typescript - Wait for promise resolve before function return
提问by EdR
Updated with working solution
更新了工作解决方案
I start with a function that grabs information from all rows selected in a table and pushes that information into a stack for later processing.
我从一个函数开始,该函数从表中选择的所有行中获取信息并将该信息推送到堆栈中以供以后处理。
for (var i = 0; i < this.selectedItems().length; i++) {
var row = this.selectedItems()[i];
let info = this.createFileReqInfo(row.Number(), FileRequestType.AssociatedDoc);
fileReqInfo.push(info);
}
My Problem: The createFileReqInfo
function returns before the asynchronous API call can return a value, so I'm not getting the right value for userCanView in the return object.
我的问题:createFileReqInfo
函数在异步 API 调用可以返回值之前返回,所以我没有在返回对象中获得 userCanView 的正确值。
createFileReqInfo = (reportId: number, fileRequestType: FileRequestType) : any => {
let fileReq = new FileRequest(reportId, fileRequestType);
var uCanView = false;
this.reportModel.getReportSecurity(reportId).done((result) => {
uCanView = result.CanViewReport;
var info: {
fileRequest: FileRequest,
userCanView: boolean
} = {
fileRequest: fileReq,
userCanView: uCanView
}
return info;
});
}
The compiler won't let me use await
here. Any ideas on how to get the function to block until the API call returns?
编译器不会让我await
在这里使用。关于如何让函数阻塞直到 API 调用返回的任何想法?
Solution
解决方案
My problem here is that there were a few levels of function calls here that I had to rework to create and resolve promises. The function that calls the API resembles something in the suggested solutions
我的问题是这里有几个级别的函数调用,我必须重新创建和解决承诺。调用 API 的函数类似于建议解决方案中的某些内容
createFileReqInfo = (reportId: number, fileRequestType: FileRequestType) : JQueryPromise<any> => {
let fileReq = new FileRequest(reportId, fileRequestType);
var uCanView = false;
var info: {
fileRequest: FileRequest,
userCanView: boolean
} = {
fileRequest: fileReq,
userCanView: uCanView
}
let dfd: JQueryDeferred<any> = $.Deferred();
this.reportModel.getReportSecurity(reportId).done((result) => {
uCanView = result.CanViewReport;
info.userCanView = uCanView;
dfd.resolve(info);
});
return dfd;
}
This now returns a promise. The problem I had is with the function that calls this one because it iterates through a list of selected items and queues up various reports to download, but only the ones that exist in that particular selection. Had to use thisanswer to figure out a way to wait for all the promises to resolve before continuing.
这现在返回一个承诺。我遇到的问题是调用这个函数的函数,因为它遍历所选项目的列表并将各种报告排队下载,但只有那些存在于特定选择中的报告。不得不使用这个答案来找出一种方法,在继续之前等待所有承诺解决。
getFileReqsFromSelectedItems = (view1: boolean, view2: boolean, view3: boolean): JQueryPromise<any> => {
var fileReqInfo: {
fileRequest: FileRequest,
userCanView: boolean
}[] = [];
let dfd: JQueryDeferred<any> = $.Deferred();
let promise: JQueryPromise<any>;
let promiseArray: JQueryPromise<any>[] = [];
for (var i = 0; i < this.selectedItems().length; i++) {
var row = this.selectedItems()[i];
if( view1 && row.HasView1() ) {
promise = this.createFileReqInfo(row.Number(), FileRequestType.AssociatedDoc1);
promiseArray.push(promise);
}
if( view2 && row.HasView2() ) {
promise = this.createFileReqInfo(row.Number(), FileRequestType.AssociatedDoc2);
promiseArray.push(promise);
}
if( view3 && row.HasView3() ) {
promise = this.createFileReqInfo(row.Number(), FileRequestType.AssociatedDoc3);
promiseArray.push(promise);
}
}
$.when.apply($, promiseArray).done(function() {
var promises = arguments;
for (var j = 0; j < promises.length; j++)
{
fileReqInfo.push(promises[j]);
}
dfd.resolve(fileReqInfo);
});
return dfd;
}
After that, it was easy to take the array of returned values and pass it to the download function.
之后,很容易获取返回值的数组并将其传递给下载函数。
downloadReports = () => {
this.getFileReqsFromSelectedItems(this.view1Check(), this.view2Check(), this.view3Check()).then((fileReqsDetails) => {
this.downloadTrialFiles(fileReqsDetails);
});
}
Whew!
哇!
采纳答案by kingdaro
For APIs that don't support promises, you can use new Promise
to create a promise yourself, call resolve
with the result of the async call, then you can use async/await syntax when calling it. More info on promises
对于不支持promise的API,可以使用new Promise
自己创建promise,resolve
使用async调用的结果进行调用,调用时可以使用async/await语法。有关承诺的更多信息
interface ReportSecurityInfo {
fileRequest: FileRequest
userCanView: boolean
}
createFileReqInfo = (reportId: number, fileRequestType: FileRequestType): Promise<any> => {
let fileReq = new FileRequest(reportId, fileRequestType);
var uCanView = false;
return new Promise((resolve, reject) => {
this.reportModel.getReportSecurity(reportId).done((result) => {
uCanView = result.CanViewReport;
var info: ReportSecurityInfo = {
fileRequest: fileReq,
userCanView: uCanView
}
resolve(info)
});
})
}
// somewhere else...
const info = await this.createFileReqInfo()
I also went ahead and split out the type of info
as its own interface for readability.
我还继续将类型拆分info
为它自己的界面以提高可读性。
回答by Reza
You can return promise from createFileReqInfo , then wait until it resolves
您可以从 createFileReqInfo 返回承诺,然后等到它解决
for (var i = 0; i < this.selectedItems().length; i++) {
var row = this.selectedItems()[i];
let info = await this.createFileReqInfo(row.Number(), FileRequestType.AssociatedDoc);
fileReqInfo.push(info);
}
Or
或者
for (var i = 0; i < this.selectedItems().length; i++) {
var row = this.selectedItems()[i];
this.createFileReqInfo(row.Number(), FileRequestType.AssociatedDoc)
.then(info => {
fileReqInfo.push(info);
});
}
Where createFileReqInfo
is defined as:
其中createFileReqInfo
定义为:
createFileReqInfo = (reportId: number, fileRequestType: FileRequestType) : Promise<any> => {
return new Promise( (resolve, reject) => {
let fileReq = new FileRequest(reportId, fileRequestType);
var uCanView = false;
this.reportModel.getReportSecurity(reportId).done((result) => {
uCanView = result.CanViewReport;
var info: {
fileRequest: FileRequest,
userCanView: boolean
} = {
fileRequest: fileReq,
userCanView: uCanView
}
resolve(info);
});
}
}