Typescript - 在函数返回之前等待promise解析

时间:2018-04-18 18:42:58

标签: typescript asynchronous

更新了工作解决方案

我从一个函数开始,该函数从表中选择的所有行中获取信息,并将该信息推送到堆栈中以供以后处理。

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);
}

我的问题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;        
    });
}

编译器不允许我在这里使用await。关于如何在API调用返回之前阻止函数的任何想法?

解决方案

我的问题是,这里有几个级别的函数调用,我不得不重做以创建和解决承诺。调用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回答来找出在继续之前等待所有承诺解决的方法。

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;
}

之后,很容易获取返回值的数组并将其传递给下载函数。

downloadReports = () => {
    this.getFileReqsFromSelectedItems(this.view1Check(), this.view2Check(), this.view3Check()).then((fileReqsDetails) => { 
        this.downloadTrialFiles(fileReqsDetails);
    });
}

呼!

2 个答案:

答案 0 :(得分:1)

您可以从createFileReqInfo返回promise,然后等到它解析

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);
}

或者

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);
            });

}

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);        
    });
    }
}

答案 1 :(得分:1)

对于不支持promises的API,您可以使用new Promise自己创建一个promise,使用异步调用的结果调用resolve,然后在调用时可以使用async / await语法它。 More info on promises

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()

我还继续将info的类型拆分为其可读性的接口。