如何等待函数在javascript中完成?

Posted

技术标签:

【中文标题】如何等待函数在javascript中完成?【英文标题】:How to wait for function to finish in javascript? 【发布时间】:2021-04-29 10:37:55 【问题描述】:

如何在 javascript 中等待函数完成? 我有 2 个函数 updateSeasonupdateFixtures,我想等待第一个函数完成后再运行下一个函数。

我的两个函数都是异步的,它们工作得很好。唯一的问题是,如果我不使用setTimeout,我需要运行两次,因为updateFixtureupdateSeason 完成之前运行,并且在第一次运行时仍然没有要获取的文件。

更新数据

const updateData = async () => 
  await updateSeason();
  await updateFixtures();
;

更新季节

    // UPDATE SEASON
const updateSeason = async () => 
  // SEASONS TEMPLATE
  let seasonsTemplate = 
    timestamp: new Date(),
    season: null,
    leagues: [],
  ;

  // FETCH LEAGUES INFO
  const leagues = await fetch(url + "leagues?subscribed=true&" + key)
    .then((response) => response.json())
    .then((data) => data.data);

  // MAP THROUGH LEAGUES
  leagues.map(async (league) => 
    const id = `$league.league_id&`;

    // FETCH SEASONS INFO
    const seasons = await fetch(url + "seasons?league_id=" + id + key)
      .then((response) => response.json())
      .then((data) => data.data);

    // MAP THROUGH LEAGUES & POPULATE SEASONS TEMPLATE
    seasons.map((season) => 
      if (season.is_current) 
        seasonsTemplate.season = `$moment(season.start_date).format("YYYY")_$moment(season.end_date).format("YYYY")`;
        seasonsTemplate.leagues.push(
          country_id: season.country_id,
          league_id: league.league_id,
          league_name: league.name,
          season_id: season.season_id,
          start_date: season.start_date,
          end_date: season.end_date,
        );
      
    );

    // CHECK / CREATE SEASON FOLDER
    const currentSeasonFolder = `./data/$seasonsTemplate.season`;
    if (!existsSync(currentSeasonFolder)) 
      await mkdir(currentSeasonFolder);
      await mkdir(`$currentSeasonFolder/matches`);
    

    // CREATE / UPDATE SEASON FILES
    await writeFile("./data/current_season.json", JSON.stringify(seasonsTemplate));
    await writeFile(`$currentSeasonFolder/season.json`, JSON.stringify(seasonsTemplate));

    console.log(`$league.name updated...`);
  );
;

更新夹具

    // UPDATE FIXTURES
    const updateFixtures = async () => 
      // FIXTURES TEMPLATE
      let fixturesTemplate = 
        timestamp: new Date(),
        season: null,
        fixtures: [],
      ;
    
      // FETCH CURRENT SEASON INFO
      const season = await fetch(api + "current_season.json").then((response) => response.json());
    
      // POPULATE FIXTURES TEMPLATE SEASON
      fixturesTemplate.season = season.season;
    
      // MAP THROUGH LEAGUES
      season.leagues.map(async (league) => 
        const id = `$league.season_id&`;
    
        // FETCH COMPETITION FIXTURES
        const fixtures = await fetch(url + "matches?season_id=" + id + key)
          .then((response) => response.json())
          .then((data) => data.data);
    
       

 // MAP THROUGH FIXTURES & POPULATE FIXTURES TEMPLATE
    fixtures.map((match) => 
      if ((match.home_team.team_id === teamId || match.away_team.team_id === teamId) && match.status !== "postponed") 
        fixturesTemplate.fixtures.push(
          match_timestamp: new Date(match.match_start_iso).getTime(),
          match_start: match.match_start_iso,
          match_id: match.match_id,
          status: match.status === "" ? "notstarted" : match.status,
          home_team: getTeamName(match.home_team.team_id),
          home_short: getShortName(match.home_team.team_id),
          away_team: getTeamName(match.away_team.team_id),
          away_short: getShortName(match.away_team.team_id),
        );
      
    );

    // SORT FIXTURES BY DATE IN ASCENDING ORDER
    fixturesTemplate.fixtures.sort((a, b) => a.match_timestamp - b.match_timestamp);

    // CREATE / UPDATE FIXTURES FILES
    const currentSeasonFolder = `./data/$season.season`;
    await writeFile(currentSeasonFolder + "/fixtures.json", JSON.stringify(fixturesTemplate));

    console.log("Fixtures updated...");
  );
;

更新:

问题在于函数本身。 async Array.prototype.mapupdateSeasonupdateFixtures 两个函数中都替换为 for 循环,现在正在工作

【问题讨论】:

leagues.map(async (league) => 这只是触发了一堆异步调用而不等待它们。使用传统的 for...of 循环。 ***.com/questions/37576685/… 【参考方案1】:

您可以只对定义的函数使用 async/await,即使您不能在异步函数之外使用“await”关键字。

所以,例如,你有一个 index.js 文件,你可以这样做:


async function main() 
  await updateSeason();
  await updateFixtures();


main()

或直接调用简写函数


(async function main() 
  await updateSeason();
  await updateFixtures();
)()

无论如何,请避免在异步函数中使用“writeFileSync”或其他“同步”函数,因为这会阻塞事件循环并降低性能。

编辑:我现在看到您正在使用带有异步回调的 Array.prototype.map 函数,这可能是问题所在。

试试看这里:https://flaviocopes.com/javascript-async-await-array-map/

或者,否则,使用标准 for 循环来处理您的联赛

【讨论】:

当我使用 writeFilemkdir 时,函数根本不起作用,然后出现错误 Callback must be a function. Received undefined 是的,因为它们是异步的,所以它们需要回调,但您可以使用与 async/await 配合使用的 fs.promises。看看这里nodejs.org/api/fs.html#fs_promises_api 我替换了从fs 导入的writeFileSyncmkdirSyncawait writeFileawait mkdirSyncfs/promises 导入,但我在第一次运行时仍然得到相同的结果 FetchError。代码更新 抱歉,我看不到更新。无论如何,看看我编辑的关于使用地图数组功能的回复。 我更新了我的代码并用标准 for 循环替换了 Array.prototype.map 函数,并且工作完美:)【参考方案2】:

为什么不只是,

async function updateData() 
  await updatedSeason();
  await updateFixtures()


updateData();

【讨论】:

这是我最初所做的,但由于某种原因无法正常工作。我认为问题出在函数本身的某个地方 @Klak031 在map 函数中的awaiting 存在问题。你正在尝试await 一些不是承诺的东西。我将尝试使用异步模拟更新我的答案。您还需要将map 包裹在Promise.all 这是调用异步函数并完美运行的正确方法。问题出在带有 Array.prototype.mapasync 的函数内部,这是对标准 for 循环的更改,现在可以正常工作了。【参考方案3】:

Async Await 可以在这里为您提供帮助,因为它们都是异步函数。

const updateData = async () => 
  await updateSeason();
  await updateFixtures();
;

【讨论】:

这是调用异步函数并完美运行的正确方法。问题出在带有 Array.prototype.mapasync 的函数内部,这是对标准 for 循环的更改,现在可以正常工作了。【参考方案4】:

你忘了在函数前加上“await”

const updateData = async () => 
  // Add await before the functions because they are async functions
  await updateSeason()       
  await updateFixtures()
;

【讨论】:

await 需要在 async 函数中使用,除非当然*** await 是操作所具有的。 这是调用异步函数并完美运行的正确方法。问题出在带有 Array.prototype.mapasync 的函数内部,这是对标准 for 循环的更改,现在可以正常工作了。

以上是关于如何等待函数在javascript中完成?的主要内容,如果未能解决你的问题,请参考以下文章

Flutter:如何在运行 JavaScript 函数并显示 html 后等待 WebView 完成加载?

如何在 Java 中等待多个任务完成?

Javascript等待Promise在返回响应之前完成for循环

如何等待此功能完成?

如何在 Javascript 中使用异步等待函数对象?

如何等待浏览器完成javascript中的重排?