首页 > 解决方案 > 在 Angular 6 中等待异步函数

问题描述

在我的 Angular 6 项目中,我需要一些建议和最佳实践技巧。

您可以在下面看到一些伪代码(请忽略任何拼写错误),但这基本上就是正在发生的事情。该项目通过几个步骤来获取新的和新鲜的数据并在向用户展示之前对其进行处理。我想要做的是让它运行所有步骤 1 直到完成,然后进入步骤 2,一旦完成,它就进入步骤 3,依此类推。这是因为某些步骤需要上一步的响应才能提出请求,这意味着我需要等待每个步骤完成,然后才能继续下一步。但是我对异步函数有一点问题。

var token;

mainFunction(){
    step1();
    console.log("Done with step 1");

    step2();
    console.log("Done with step 2");

    step3();
    console.log("Done with step 3");
}

step1(){
    console.log("Step 1...");
    var data1 = getData();
    // Does things with data1
}

step2(){
    console.log("Step 2...");
    var data2 = getData();
    // Does things with data2
}

step3() {
    console.log("Step 3...");
    var data3 = getData();
    // Does things with data3
}

async getData(){
    await getAccessToken();

    var result;

    console.log("Getting data...");

    // Makes a request to an API.
    this.http.post("URL", token)
    .map(response => response.json())
    .toPromise()
    .then((response: any) => {
        console.log("Got the data!");

        // Processing the response
        result = response;
    }
    return result;
}

async getAccessToken(){
    console.log("Getting access token...");

    let accessToken = await getToken(); //Returns a Promise

    this.token = accessToken;
    console.log("Got the token!");

    return Promise.resolve(true);
}

问题始于 getAccessToken 函数中的 getToken() 。这是一个返回承诺的异步函数,这意味着它不等待响应。没问题,只需设置一个等待就可以了!

但是即使 getAccessToken() 现在等待 getToken() 完成,getData() 也不会等待 getAccessToken() 完成等待 getToken()。解决方案?我返回了一个 Promise 并将 await 放入 getData() 中。但是我没有解决我只是移动它的问题。

现在 getData() 现在等待 accessToken 在执行请求之前完成,但 step1、step2 和 step 3 不会等待。解决方案是一直返回承诺并在每个函数上设置等待吗?我希望有一种更清洁的方法来做到这一点,只需将 await 设置在它实际需要等待的地方,一切都会停止并等待它完成。

有没有一种干净的方法来做到这一点?什么是最佳实践?

这是我想要的输出:

这是我得到的输出:

标签: javascripttypescriptasynchronousasync-awaitangular6

解决方案


解决方案是一直返回承诺并在每个函数上设置等待吗?

是的(但请注意,您不需要像在下面那样明确地getAccessToken执行此操作)。如果函数依赖于异步函数的结果,那么该函数也必须是异步的。这一路冒泡。

如果要按顺序mainFunction处理step1step2step3,并且它们依赖于异步结果,那么它们必须是异步的,并且mainFunction必须是异步的(并且使用它的任何东西都必须是异步的):

async function mainFunction() {
    console.log("mainFunction start");
    await step1();
    console.log("step1 done");
    await step2();
    console.log("step2 done");
    await step3();
    console.log("step3 done");
    console.log("mainFunction done");
}
async function step1() {
    await getData();
}
async function step2() {
    await getData();
}
async function step3() {
    await getData();
}
async function getData() {
    await getAccessToken();
    return Math.floor(Math.random() * 1000);
}
async function getAccessToken() {
    await asyncStandIn();
}
function asyncStandIn() {
    return new Promise(resolve => setTimeout(resolve, 800));
}

// Top level entry
(async () => {
    mainFunction();
})().catch(error => {
    console.error(error);
});

Re getAccessToken: 把它变成一个async函数就意味着它总是返回一个承诺。不需要return Promise.resolve(true);,您可以删除该行。getAccessToken(不过,调用的函数没有返回访问令牌的 [承诺],这有点奇怪。)

更多阅读;我的看法是,投票结束您的问题作为以下内容的副本是不正确的,但其他人可能会有所不同:


推荐阅读