打字稿-承诺。异步等待呼叫依赖于另一个呼叫

时间:2020-07-19 17:08:32

标签: javascript typescript asynchronous es6-promise

我正在尝试通过并行执行请求或任何其他可能的方式来提高加载数据的性能。我是Javascript / Typescript编码方式的新手。我来自Java。 最近,我发现了有关异步等待和承诺的信息。

我有两种方法。第一个是独立的,仅执行一个请求。第二个依赖于另一个请求的输出值(在这种情况下为“数字”值)。

我按此顺序调用这些函数。

private run(): void {
    this.populatePostTextData(list, 3);
    this.populateCustomerNameData(list, 5);
}

以下是我的担忧:

两者似乎都不并行/同时运行。等待populatePostTextData()完成(然后将值设置为DOM),然后等待populateCustomerNameData()(将值再次设置为DOM)

第二种方法有2个请求。我不知道如何构造await。我试图锁住他们

await Service.Current.executeRequest(getNumber).then((response: Response) => {
    number = response.items[0]["CustomerNumber"];
    console.log("Customer No retrieved: " + number);
    await Service.Current.executeRequest(getNumber)... 
}).catch((response: Response) => {
    console.log("Error: " + response.errorMessage);
});

但是我在await Service.Current.executeRequest(getNumber)...上收到一个错误,因为它是嵌套的,所以它必须在异步中。似乎没有将其读取为异步方法中包含的内容

第一种方法

    async populatePostTextData(list: IList, columnNum: number) {
        const columnId = "C" + columnNum;
        for (let i = 0; i < list.getData().getLength(); i++) {
            let referenceOrderNo = list.getData().getItem(i).C1;
            let referenceOrderLine = list.getData().getItem(i).C2;
    
            const request = new Request("...");
            let postTextData = {};
            await Service.Current.executeRequest(request).then((response: Response) => {
                let postText = response.items[0]["PostText"];
                postTextData[columnId] = postText;
                postTextData["id_" + columnId] = "R" + (i + 1) + columnId;
                $.extend(list.getData().getItem(i), postTextData);
            }).catch((response: Response) => {
                console.log("Error: " + response.errorMessage);
            });
        }
    }
    

第二种方法 getNumber应该首先执行,因为变量number用于getName

    async populateCustomerNameData(list: IList, columnNum: number) {
        const columnId = "C" + columnNum;
    
        for (let i = 0; i < list.getData().getLength(); i++) {
            let referenceOrderNo = list.getData().getItem(i).C1;
            let referenceOrderLine = list.getData().getItem(i).C2;
    
            let number = "";
            const getNumber = new Request(".../");
            await Service.Current.executeRequest(getNumber).then((response: Response) => {
                number = response.items[0]["CustomerNumber"];
                console.log("Customer No retrieved: " + number);
            }).catch((response: Response) => {
                console.log("Error: " + response.errorMessage);
            });
    
            let customerName = {};
            const getName = new Request("...");
            getName.setParam(1,number);
            await Service.Current.executeRequest(getName).then((response: Response) => {
                const name = response.items[0]["CustomerName"];
                customerName[columnId] = name;
                customerName["id_" + columnId] = "R" + (i + 1) + columnId;
                $.extend(list.getData().getItem(i), customerName);
            }).catch((response: Response) => {
                console.log("Error: " + response.errorMessage);
            });
        }
    }

我将不胜感激任何建议或解决方案

谢谢。

2 个答案:

答案 0 :(得分:0)

因此,第二个请求似乎取决于第一个请求的解析,因为您必须传递数字。在这种情况下,您可以尝试以下操作:

const runner = async() => {
    try {
    const response = await firstRequest();
    // At this point you can assume that the first request is completed successfully and you can extract what you need from the response.
    const number = response.number 
    await secondRequest(number);
    } catch(error) {
        console.log(error):
    }
}

然后,您可以在需要启动此过程时调用runner或任何您想调用的名称。这两个请求函数必须返回promise,或者本身是异步隐式返回promise的异步函数。

您还可以使用.then关键字或await关键字来组织程序的异步部分的流程。也可以同时使用它们,但是通常您会看到其中一个。如果您想使用.then,可以执行以下操作:

const runner = () => {
    firstRequest()
      // get the number from the first response
     .then((res) => res.number))
     .then((num) => secondRequest(num))
     .catch((error) => console.log(error)):
}

虽然await是较新的语法,所以我可能会建议这样做。它也使代码更具可读性。

欢呼

答案 1 :(得分:0)

我看不到任何阻止第二个功能运行的东西,但是我看到的是您在各自的 for循环中的请求被await阻止了。您应该考虑对要并行执行的呼叫使用Promise.all或删除await

此示例代码应突出显示您需要了解的行为,以便几乎了解所有关于Promises和Async / Await的信息。

let hrstart = process.hrtime();

function time() {
    return `${process.hrtime(hrstart)[0]}s`;
}

function wait(time) {
    return new Promise((resolve) => {
        setTimeout(() => {
            resolve(time);
        }, time * 1000);
    });
}

async function blocking() {
    for (let index = 5; index < 10; index++) {
        let complete = await wait(index);
        console.log('blocking', complete, time());
    }
}

async function single() {
    let complete = await wait(2);
    console.log('single:', complete, time());
}

async function nonBlocking() {
    let jobs = [];
    for (let index = 5; index < 10; index++) {
        jobs.push(wait(index));
    }
    return Promise.all(jobs).then((res) => {
        for (let index = 0; index < res.length; index++) {
            console.log('non-blocking:', res[index], time());
        }
    });
}

blocking();
single();
nonBlocking();

结果如下:

single: 2 2s
blocking 5 5s
non-blocking: 5 9s
non-blocking: 6 9s
non-blocking: 7 9s
non-blocking: 8 9s
non-blocking: 9 9s
blocking 6 11s
blocking 7 18s
blocking 8 26s
blocking 9 35s