Ожидание асинхронных функций в Angular 6 - PullRequest
0 голосов
/ 30 октября 2018

Мне нужны некоторые предложения в моем угловом проекте 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);
}

Проблема началась с getToken () внутри функции getAccessToken. Это асинхронная функция, которая возвращает обещание, что означает, что оно не ожидает ответа. Нет проблем, просто установите ожидание, и оно отлично работает!

Но даже если getAccessToken () теперь ожидает завершения getToken (), getData () не ждет, пока getAccessToken () завершит ожидание getToken (). Решение? Я вернул Promise и поместил await в getData (). Но я не решил проблему, я только переместил это.

Сейчас getData () теперь ожидает завершения accessToken, прежде чем выполнять запрос, но step1, step2 и step 3 не ждут. Является ли решение вернуть обещание полностью и установить ожидание для каждой функции? Я надеюсь, что есть более чистый способ сделать это и просто установить ожидание, где он действительно должен ждать, и все остановится и будет ждать, пока это не закончится.

Есть ли чистый способ сделать это? Что такое лучшая практика?

Это вывод, который я хочу:

  • Шаг 1 ...
  • Получение токена доступа ...
  • Получил жетон!
  • Получение данных ...
  • Получил данные!
  • Готово с шагом 1
  • Шаг 2 ...
  • Получение токена доступа ...
  • Получил жетон!
  • Получение данных ...
  • Получил данные!
  • Готово с шагом 2
  • Шаг 3 ...
  • Получение токена доступа ...
  • Получил жетон!
  • Получение данных ...
  • Получил данные!
  • Готово с шагом 3

Это вывод, который я получаю:

  • Шаг 1 ...
  • Получение токена доступа ...
  • Готово с шагом 1
  • Шаг 2 ...
  • Получение токена доступа ...
  • Готово с шагом 2
  • Шаг 3 ...
  • Получение токена доступа ...
  • Готово с шагом 3
  • Получил жетон!
  • Получение данных ...
  • Получил данные!
  • Получил жетон!
  • Получение данных ...
  • Получил данные!
  • Получил жетон!
  • Получение данных ...
  • Получил данные!

1 Ответ

0 голосов
/ 30 октября 2018

Является ли решение полностью вернуть обещание и установить ожидание для каждой функции?

Да (но учтите, что вам не нужно делать это явно , как в getAccessToken, подробнее ниже). Если функция полагается на результат асинхронной функции, то эта функция также должна быть асинхронной. Это пузыри все время вверх.

Если вы хотите, чтобы mainFunction обрабатывал step1, step2 и step3 по порядку и полагались на асинхронные результаты, то они должны быть асинхронными, а 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 не возвращает [обещание] токена доступа.)

Больше чтения; я считал, что голосование за закрытие вашего вопроса в двух экземплярах не будет правильным, но другие могут отличаться:

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...