Правильный способ использования async / await в приложениях Angular и Ionic - PullRequest
0 голосов
/ 03 января 2019

У меня есть приложение Ionic, где на одной из страниц я вставляю некоторые записи в SQLite DB после того, как пользователь заполняет форму. Чтобы убедиться, что пользователь переходит на следующую страницу только после вставки данных в БД, я использую функцию async/await.

Однако я не уверен, правильно ли я использую эту функцию, потому что в журналах консоли указано иное.

В журналах консоли я вижу сообщение "******Navigate to Home page", а затем "Executed INSERT USER CONTRACT sql...", что ставит меня в тупик, поскольку оператор навигации должен быть последним, который должен отображаться в журналах консоли.

Я перебрал эту SO-ссылку ( Typescript sleep ) и некоторые другие онлайн-статьи, но не уверен, что мне что-то не хватает.

Журналы консоли:

[app-scripts] [23:07:08]  console.log: Looping through the contracts data to store them in DB....
[app-scripts] [23:07:08]  console.log: Into the insertUserContract method........
[app-scripts] [23:07:08]  console.log: cropId: 4
[app-scripts] [23:07:08]  console.log: contract:
[app-scripts]             {"contractName":"C1","contractBushels":"1000","contractPrice":"5","contractFulfillmentDt":"2019-01"}
[app-scripts] [23:07:08]  console.log: ***********Navigating to Home page now.....
[app-scripts] [23:07:08]  console.log: contractDollarAmt: 5000
[app-scripts] [23:07:08]  console.log: ****************Into the home page
[app-scripts] [23:07:08]  console.log: Loading all user crops from DB....
[app-scripts] [23:07:08]  console.log: this.userCropCfgs: undefined
[app-scripts] [23:07:08]  console.log: Executed INSERT USER CONTRACT sql...{"rows":{"length":0},"rowsAffected":1,"insertId":1}
[app-scripts] [23:07:08]  console.log: Executed saveUserCrop sql...{"rows":{"length":0},"rowsAffected":1,"insertId":1}
[app-scripts] [23:07:08]  console.log: rowsAffected: 1
[app-scripts] [23:07:08]  console.log: @@@@@@@result: 1

UserContractPage.ts

addUserContract(val: any) {
    let myUserContract = val as UserContractTxModel;
    let cropId: number = myUserContract.cropId;
    let contractCnt = myUserContract.contracts.length;
    let contracts: ContractTxModel[] = myUserContract.contracts;

    console.log("Looping through the contracts data to store them in DB....");
    (async () => {
      let results: number[] = [];
      for (let i = 0; i < contractCnt; i++) {
        this.userContractProvider.insertUserContract(cropId, contracts[i])
          .then((result) => {
            console.log("@@@@@@@result: " + result);
            results.push(result);
          })
          .catch(e => console.error(JSON.stringify(e)));
      }

      //navigate only when the above code executes and data gets inserted in DB
      await this.navigate();
    })();
  }

  private navigate() {
    console.log("***********Navigating to Home page now.....");
    this.navCtrl.push(HomePage);
  }

UserContractProvider.ts (фактически вставляет данные в БД)

insertUserContract(cropId: number, contract: ContractTxModel): Promise<number> {
    console.log("Into the insertUserContract method........");
    console.log("cropId: " + cropId);
    console.log("contract: " + JSON.stringify(contract));
    return this.databaseProvider.getDatabase().then(database => {
      let contractDollarAmt = contract.contractBushels * contract.contractPrice;
      console.log("contractDollarAmt: " + contractDollarAmt);
      return database.executeSql(SQL_INSERT_INTO_USER_CONTRACT_TX_TABLE, [
        cropId, contract.contractName,
        contract.contractBushels, contract.contractPrice, contractDollarAmt,
        contract.contractFulfillmentDt
      ])
        .then((data) => {
          console.log("Executed INSERT USER CONTRACT sql..." + JSON.stringify(data));
          console.log("Executed saveUserCrop sql..." + JSON.stringify(data));
          console.log("rowsAffected: " + data.rowsAffected);
          return data.rowsAffected;
        }).catch((e) => {
          console.error("Error: " + JSON.stringify(e));
        });
    });
  }

Ответы [ 2 ]

0 голосов
/ 03 января 2019

Хотя это могло бы сработать для вас, правильный способ сделать это - использовать функцию Promise.all , которая позволяет складывать обещания и ждать их выполнения, прежде чем продолжить.

в предложенном ответе вы запускаете одну вставку за раз, что может быть тем, чего вы пытаетесь достичь.

Кроме того, вы используете await с then (). Catch (), которыйсвоего рода перебор.

Однако, если вы хотите запустить ваши вставки параллельно, вы можете сделать следующее:

async yourFunctionName() {
    const promises = [];
    for (let i = 0; i < contractCnt; i++) {
      promises.push(this.userContractProvider.insertUserContract(cropId, contracts[i]));
    }
    results = await Promise.all(promises);
    // When all the inserts will complete, this navigate() will execute and the 
    //result of each insert is stored in the array results
     this.navigate();
}
0 голосов
/ 03 января 2019

Единственное, что вы await делаете в цикле for, это await this.navigate(); - остальные Обещания просто объявляются, но не ожидаются. Если вы хотите, чтобы цикл продолжался только после завершения insertUserContract, поместите await перед вызовом:

for (let i = 0; i < contractCnt; i++) {
  await this.userContractProvider.insertUserContract(cropId, contracts[i])
    .then((result) => {
      console.log("@@@@@@@result: " + result);
      results.push(result);
    })
    .catch(e => console.error(JSON.stringify(e)));
}

//navigate only when the above code executes and data gets inserted in DB
this.navigate();

Также обратите внимание, что navigate не является асинхронным, поэтому не await это.

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