如何让外部类的JavaScript async异步方法正常运行?
问题原因
Array.prototype.forEach是同步迭代方法,不会等待传入的异步回调执行完成:你给forEach传入的async回调是独立的异步任务,forEach只会同步触发所有回调,不会等回调内的await请求返回就会继续执行后续代码。所以loadObject3Ds执行时,所有fetch请求刚触发就直接把空数组赋值给了this.object3Ds,后续请求完成才会往数组里推送元素。loadObject3Ds本身没有声明为异步方法,调用时也没有加await,所以onUserCreate执行完project.loadObject3Ds()后会立刻执行后续的数组遍历逻辑,此时数组还没有任何元素。- 控制台打印的对象是引用类型,预览时显示的是打印瞬间的状态,展开时才会读取对象的最新值,所以会出现预览是空数组、展开后有内容的情况。
修复方案
第一步:修改Project.js中的loadObject3Ds方法
将forEach迭代改为map生成Promise数组,用Promise.all等待所有异步请求完成后再给this.object3Ds赋值,同时将方法声明为异步:
export default class Project { constructor(project) { this.object3DsIds = project.object3DsIds; this.object3Ds = new Array(); } async loadObject3Ds() { // 把每个id对应的异步请求包装成Promise,生成Promise数组 const object3DPromises = this.object3DsIds.map(async (object3DId) => { const object3D = new Object3D(); const objectUrl = 'https://localhost:44555/api/object3Ds/' + object3DId const object = await fetch(objectUrl).then(res => res.json()); object3D.id = object.id; return object3D; }); // 等待所有请求完成,拿到完整的数组 this.object3Ds = await Promise.all(object3DPromises); } }
第二步:修改index.js中的onUserCreate函数
将onUserCreate声明为异步函数,调用loadObject3Ds时添加await等待执行完成:
import Project from "./AppStructure/Models/Project.js"; let project; let projectAPI = await fetch(projectUrl).then(res => res.json()); // 声明为异步函数 async function onUserCreate() { project = new Project(projectAPI); // 等待loadObject3Ds执行完成,所有元素加载完毕再走后续逻辑 await project.loadObject3Ds(); console.log(project); console.log(project.object3Ds); console.log(project.object3Ds[0]); project.object3Ds.forEach(function (object) { doSomething(object); }); } function onUserUpdate() { requestAnimationFrame(onUserUpdate); renderSomething(); } onUserCreate(); onUserUpdate();
内容的提问来源于stack exchange,提问作者BartoszPe
相关产品推荐
相关产品推荐

