【问题标题】:Can't find bug - async function - returning too quickly找不到错误 - 异步函数 - 返回太快
【发布时间】:2021-12-19 06:59:44
【问题描述】:

我正在尝试根据 API 调用对 3rd aprty 的响应创建一系列“INSERT INTO”查询。

API 响应被分解为不同的页面,我循环浏览数据,然后循环浏览页面,尝试更新每条数据的字符串。

正在到达响应的所有页面,并且正在将数据添加到总字符串中,但正在发生的情况是返回发生得太早 - 也就是说,除了最后一页之外的所有数据都被返回。我不知道为什么返回对象bulkInsertString 被返回得太早了一页。关注的函数是getBulkInsert 函数...我认为它与while 循环中的条件有关,一旦到达最后一页就停止运行。最后一页页面上的数据肯定已经到达,因为它正在记录在console.log('string added',forename,surname)...中,但是这样做太晚了。我想知道我是否在某处错过了“等待”。谁能看到我必须如何调整我的代码以确保我返回所有数据,包括最后一页?我以为既然 return 语句是在 while 循环之后,那么一旦 while 循环完成它就会返回?

当服务器开始运行时,'syncStaffRoll'函数被调用:

const axios = require("axios");
const generateString = require("./queryBuilders/CreateInsertInto");
const sql = require("mssql");

const getBulkInsert = async (schoolId, myDate) => {
  var queryStart = "";
  var bulkInsertString = "";
  var lastPage = false;

  var endPoint = `***`;
  var i = 1;
  while (!lastPage) {
    console.log(`currently on element ${i} of response`);

const config = {
  method: "get",
  url: endPoint,
  headers: {
    Authorization: "Bearer " + process.env.TOKEN,
  },
};

await axios(config).then((response) => {
  const staffArray = response.data.data;
  console.log(
    `${staffArray.length} staff objects received in this API call`
  );
  lastPage = !response.data.meta.pagination.more;
  endPoint = response.data.meta.pagination.next;

  if (lastPage) {
    console.log("this is the final page");
  }

  staffArray.forEach(async (staffMember) => {
    try {
      const { id, surname, forename, contact_details } = staffMember;

      const { data } = contact_details;
      const { emails } = data;
      const { primary, work } = emails;
      const getEmail = () => {
        if (work) {
          return work;
        } else {
          return primary;
        }
      };

      var nextString = await generateString("SyncStaff", "UpdatedAt", {
        StaffId: id,
        Surname: surname.replace(/'/g, '"'),
        FirstName: forename.replace(/'/g, '"'),
        StaffEmail: getEmail(),
        StaffRole: "Staff",
        UpdatedAt: myDate,
      });
      bulkInsertString = bulkInsertString + nextString;
      console.log("string added", forename, surname);
      // console.log(bulkInsertString);
    } catch (err) {
      console.log(`error in staffMember ${staffMember.id}`, err);
      // console.log(err);
    }
  });
});
i += 1;


}
  return bulkInsertString;
};

const getQuery = async (schoolId, myDate) => {
  const queryStart = `
  BEGIN TRANSACTION [Tran1]\n
    BEGIN TRY\n
  
  `;
  const queryEnd = `
      COMMIT TRANSACTION [Tran1]\n
    END TRY\n
    BEGIN CATCH \n
      ROLLBACK TRANSACTION [Tran1]\n
    END CATCH
  `;
  const bulkInsertString = await getBulkInsert(schoolId, myDate);

  const removalString = `DELETE FROM SyncStaff where UpdatedAt != '${myDate}'`;

  const queryString = queryStart + bulkInsertString + removalString + queryEnd;

  return queryString;
};

const performQuery = async (query) => {
  console.log("trying to perform query", query);
  const sqlConfig = {
    user: process.env.DB_USER,
    password: process.env.DB_PWD,
    database: process.env.DB_NAME,
    server: process.env.DB_SERVER,
    pool: {
      max: 10,
      min: 0,
      idleTimeoutMillis: 30000,
    },
    options: {
      encrypt: true, // for azure
      trustServerCertificate: false, // change to true for local dev / self-signed certs
    },
  };

  const runQuery = async () => {
    try {
      // make sure that any items are correctly URL encoded in the connection string
      await sql.connect(sqlConfig);
      const result = await sql.query(query);
      return "Query Completed";
    } catch (err) {
      console.log(err);
      return err;
    }
  };

  const result = await runQuery();
  return result;
};

const syncStaffRoll = async (schoolId) => {
  const d = new Date();
  const myDate = d.toString("en-AU");

  //generates the query to be used
  const query = await getQuery(schoolId, myDate);

  console.log(query);

  // const queryResult = await performQuery(query);

  // console.log(queryResult);
};

module.exports = syncStaffRoll;

【问题讨论】:

  • 你为什么要结合await.then()?使用其中之一,而不是两者。
  • 你不应该再使用.forEach了。请改用for( of )
  • generateString的定义是什么?

标签: javascript node.js api asynchronous async-await


【解决方案1】:

forEachasync...await 相比有点问题。 我也遇到过几次这个问题。 您应该将提供给forEach 的函数创建到一个单独的名为async 的函数中,并在for...of 循环中使用它。

【讨论】:

  • 非常感谢,加布里埃尔。这已经解决了问题。
【解决方案2】:

您的forEach 是同步的,因此它不会等待您的承诺解决。

这一行:

staffArray.forEach(async (staffMember) => {

应该使用Promise.allmap 而不是forEach,这样你就有了一系列可以使用的承诺。

await Promise.all(staffArray.map(async (staffMember) => { 
  // your async code
})

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2019-02-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-08-24
    • 2018-02-15
    相关资源
    最近更新 更多