如何等待函数在javascript中完成?
Posted
技术标签:
【中文标题】如何等待函数在javascript中完成?【英文标题】:How to wait for function to finish in javascript? 【发布时间】:2021-04-29 10:37:55 【问题描述】:如何在 javascript 中等待函数完成?
我有 2 个函数 updateSeason
和 updateFixtures
,我想等待第一个函数完成后再运行下一个函数。
我的两个函数都是异步的,它们工作得很好。唯一的问题是,如果我不使用setTimeout
,我需要运行两次,因为updateFixture
在updateSeason
完成之前运行,并且在第一次运行时仍然没有要获取的文件。
更新数据
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.map
在 updateSeason
和 updateFixtures
两个函数中都替换为 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 循环来处理您的联赛
【讨论】:
当我使用writeFile
和 mkdir
时,函数根本不起作用,然后出现错误 Callback must be a function. Received undefined
是的,因为它们是异步的,所以它们需要回调,但您可以使用与 async/await 配合使用的 fs.promises。看看这里nodejs.org/api/fs.html#fs_promises_api
我替换了从fs
导入的writeFileSync
和mkdirSync
从await writeFile
和await mkdirSync
从fs/promises
导入,但我在第一次运行时仍然得到相同的结果 FetchError。代码更新
抱歉,我看不到更新。无论如何,看看我编辑的关于使用地图数组功能的回复。
我更新了我的代码并用标准 for 循环替换了 Array.prototype.map
函数,并且工作完美:)【参考方案2】:
为什么不只是,
async function updateData()
await updatedSeason();
await updateFixtures()
updateData();
【讨论】:
这是我最初所做的,但由于某种原因无法正常工作。我认为问题出在函数本身的某个地方 @Klak031 在map
函数中的await
ing 存在问题。你正在尝试await
一些不是承诺的东西。我将尝试使用异步模拟更新我的答案。您还需要将map
包裹在Promise.all
中
这是调用异步函数并完美运行的正确方法。问题出在带有 Array.prototype.map
和 async
的函数内部,这是对标准 for
循环的更改,现在可以正常工作了。【参考方案3】:
Async Await 可以在这里为您提供帮助,因为它们都是异步函数。
const updateData = async () =>
await updateSeason();
await updateFixtures();
;
【讨论】:
这是调用异步函数并完美运行的正确方法。问题出在带有Array.prototype.map
和 async
的函数内部,这是对标准 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.map
和 async
的函数内部,这是对标准 for
循环的更改,现在可以正常工作了。以上是关于如何等待函数在javascript中完成?的主要内容,如果未能解决你的问题,请参考以下文章
Flutter:如何在运行 JavaScript 函数并显示 html 后等待 WebView 完成加载?