如何避免回调地狱实现Fabric.js SVG图片有序加载?
解决Fabric.js异步加载SVG数组顺序问题的优雅方案
嘿,我懂你现在的困扰——异步加载SVG时没法保证数组里的元素顺序,用回调嵌套又搞得代码又长又不灵活对吧?其实用Promise + async/await就能完美解决这个问题,既能控制顺序,又能让代码保持简洁易维护。
第一步:把加载函数改成返回Promise
首先我们把makeMySvg改造为返回Promise的函数,这样就能用async/await来处理异步流程,摆脱回调嵌套:
var axles = []; // 改造后的makeMySvg,返回Promise function makeMySvg(urlName, posx, posy) { return new Promise((resolve) => { fabric.loadSVGFromURL(urlName, function(objects) { var obj = new fabric.util.groupSVGElements(objects, { top: posx, left: posy, opacity: 1, scaleX: 1, scaleY: 1, objectCaching: true }); canvas.add(obj); resolve(obj); // 加载完成后返回SVG对象 }); }); }
第二步:控制加载顺序与数组位置
现在有两种常见的加载方式,你可以根据需求选择:
方式1:顺序加载(严格保证数组顺序)
如果你需要SVG严格按照你指定的顺序加载并推入数组,用async/await配合for...of循环就可以实现:
// 异步加载函数,处理顺序加载 async function loadSvgsInOrder() { // 按你想要的顺序定义SVG列表,数组顺序就是最终axles的顺序 const svgTasks = [ { url: 'holes.svg', x: 100, y: 100 }, { url: 'wheel.svg', x: 200, y: 200 }, { url: 'frame.svg', x: 300, y: 300 } ]; // 逐个加载,确保顺序 for (const task of svgTasks) { const svgObj = await makeMySvg(task.url, task.x, task.y); axles.push(svgObj); } // 所有SVG加载完成后执行后续操作 console.log(axles.length); // 这里会等于svgTasks的长度 canvas.renderAll(); } // 启动加载 loadSvgsInOrder();
方式2:并行加载(效率更高,仍保证数组顺序)
如果不需要严格按顺序加载,但希望最终数组的顺序和你定义的任务列表一致,可以用Promise.all,这样所有SVG会同时加载,效率更高:
async function loadSvgsInParallel() { const svgTasks = [ { url: 'holes.svg', x: 100, y: 100 }, { url: 'wheel.svg', x: 200, y: 200 }, { url: 'frame.svg', x: 300, y: 300 } ]; // 生成所有加载Promise const loadingPromises = svgTasks.map(task => makeMySvg(task.url, task.x, task.y)); // 等待所有加载完成,结果数组顺序和svgTasks完全一致 axles = await Promise.all(loadingPromises); console.log(axles.length); canvas.renderAll(); } // loadSvgsInParallel();
为什么这个方案更好?
- 摆脱了回调地狱,代码结构更清晰,可读性更强
- 完全可控数组中SVG对象的位置,不管是顺序还是并行加载都能保证顺序
- 灵活性高:想添加新的SVG,只需要在
svgTasks数组里新增一项即可,不用修改加载逻辑
内容的提问来源于stack exchange,提问作者Michael Roebbeling
相关产品推荐
相关产品推荐

