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

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-21 05:21:58  来源:igfitidea点击:

Typescript - Wait for promise resolve before function return

typescriptasynchronous

提问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 createFileReqInfofunction 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 awaithere. 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 Promiseto create a promise yourself, call resolvewith 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 infoas 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 createFileReqInfois 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);        
    });
    }
}