为什么这段示例代码中的async await逻辑无法正常运行?
核心问题根源
你写的await完全没有起到等待效果。await语法的生效前提是其后跟着的任务返回Promise对象,你当前的createPost是没有任何返回值的普通函数,执行完直接同步返回undefined,await碰到非Promise类型的值会立刻放行后续代码,根本不会等待函数内部的setTimeout逻辑跑完。
实际运行执行时序
按现有代码的事件循环顺序,最终输出和预期的偏差来自时间差:
- 程序初始化
posts数组后直接执行init() - 调用
createPost,触发内部2秒延迟的数组push逻辑。因为函数没有返回Promise,await立刻拿到空值、没有任何停顿,直接执行下一行的getPosts() - 调用
getPosts,触发内部1秒延迟的遍历打印逻辑 - 1秒整,
getPosts的定时器触发,遍历打印posts数组——此时createPost的2秒定时器还没到触发时间,数组里只有最初的2条数据,控制台只会输出1、2 - 2秒整,
createPost的定时器才把第三条数据push进数组,此时打印逻辑早就执行结束,自然看不到预期的第三条输出。
修正代码
给所有需要被等待的异步函数加上Promise封装,在异步操作完成时调用resolve标记任务完成状态,await就能正常实现顺序控制:
let posts = [ {name: '1', data: 'Hi1'}, {name: '2', data: 'Hi2'}, ] // 给getPosts增加Promise返回值,适配await等待 function getPosts() { return new Promise((resolve) => { setTimeout(() => { posts.forEach((post) => { console.log(post.name) }) resolve() }, 1000) }) } // 给createPost增加Promise返回值,适配await等待 function createPost(post) { return new Promise((resolve) => { setTimeout(() => { posts.push(post) resolve() }, 2000) }) } async function init() { // 现在await会等待2秒,直到新post被push进数组才继续执行 await createPost({name: '3', data: 'hey'}) // 此时数组已包含3条数据,调用getPosts即可完整打印全部内容 await getPosts() } init();
补充说明:如果仅修正
createPost的Promise返回值,哪怕不给getPosts做封装,最终打印结果也能包含第三条数据——但这是因为getPosts本身的1秒延迟刚好在createPost的2秒延迟之后触发,属于巧合时序。要稳定实现代码逻辑和执行顺序的对应,必须把所有基于setTimeout的异步操作都封装成可被await等待的Promise形式。
内容的提问来源于stack exchange,提问作者snasri8
相关产品推荐
相关产品推荐

