You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Safari加载Three.js异步资源报SyntaxError: unexpected identifier 'loadAssets'

问题原因

你遇到的Safari语法报错是顶层await特性兼容性导致的:

  • 你的代码中直接在ES模块顶层编写了const {kitchenModel,...} = await loadAssets();语句
  • Safari直到15.4版本才支持顶层await特性,低于该版本的iOS/MacOS Safari都会将顶层的await识别为非法语法,进而抛出你遇到的报错。

解决方案

将所有依赖loadAssets返回结果的逻辑,全部包裹在异步立即执行函数(IIFE)中,避免直接在模块顶层使用await。示例修改如下:

import * as THREE from "./dependencies/three.module.js";
import { loadAssets } from "./loader.js";
import gsap from "./dependencies/gsap/index.js";

// 先定义待导出的变量占位
export let burger, rapper, skater, muppie, gamer, kitchen, chef;

var lastNumber;
var nextNumber;

// 所有依赖资源加载结果的逻辑都放入异步IIFE中
(async function init() {
  const {kitchenModel, 
    burgerModel,
    rapperModel,
    skaterModel,
    muppieModel,
    gamerModel,
    chefModel} = await loadAssets();

  function randomExcluded(lastNumber) {
    var n = Math.floor(Math.random() * (3-0) + 0);
    if (n >= lastNumber) n++;
    return n;
  }

  function nextModel(last){
    var arr;
    if(last === 0){
        arr = [1,2,3,4];
    }
    else if(last === 1){
        arr = [0,2,3,4];
    }
    else if(last === 2){
        arr = [0,1,3,4];
    }
    else if(last === 3){
        arr = [0,1,2,4];
    }
    else if(last === 4){
        arr = [0,1,2,3]
    }
    return arr[Math.floor(Math.random() * (3-0) + 0)]
  }
 
  export const modelSwitcher = (delta) =>{
    var modelNumber = nextModel(lastNumber);
    console.log(lastNumber);
    console.log(modelNumber)
    switch(modelNumber){
        case 0:
            burger.animate(delta);
            console.log('burger');
            break;
        case 1:
            rapper.animate(delta);
            console.log('rapper');
            break;
        case 2:
            skater.animate(delta);
            console.log('skater');
            break;
        case 3:
            muppie.animate(delta);
            console.log('muppie');
            break;
        case 4: 
            gamer.animate(delta);
            console.log('gamer');
            break;
    }
  }

  class Burger{
    constructor(model,model_name,model_number){
        this.model_number = 0;
        this.model = burgerModel;
        this.model_name = 'burger';
        this.onCreate()
    }
    onCreate(){
        this.model.name = this.model_name;
        this.model.scale.set(.25,.25,.25);
        this.model.position.set(1,0,-.6);
    }
    animate(delta){
        const timeline = gsap.timeline({ease: "linear"});
        timeline.to(this.model.position,{y:1.1,duration:.3+delta,ease:'linear'})
        timeline.to(this.model.position,{z:2.2,duration:.8+delta,ease:'linear'})
        timeline.to(this.model.rotation,{y:-1.5,duration:.1+delta,ease:'linear'})
        timeline.to(this.model.position,{x:-1.1,duration:.8+delta,ease:'linear'})
        timeline.add(()=>lastNumber=this.model_number)
        timeline.add(()=>{modelSwitcher(delta)})
        timeline.to(this.model.rotation,{y:-3.2,duration:.1+delta,ease:'linear'})
        timeline.to(this.model.position,{z:-0.6,duration:.8+delta,ease:'linear'})
        timeline.to(this.model.position,{y:0,duration:.3+delta,ease:'linear'})
        timeline.add(()=>{this.model.visible = false})
        timeline.to(this.model.position,{x:1.12,duration:.1,ease:'linear'})
        timeline.to(this.model.rotation,{y:0,duration:.1,ease:'linear'})
        timeline.add(()=>{this.model.visible = true})
    }
    add(scene){
        scene.add(this.model)
    }
  }

  // 其余Rapper、Skater、Muppie、Gamer、Kitchen、Chef类的代码和原代码完全一致,放在IIFE内部即可

  // 实例化操作放在IIFE内部,给外部导出的变量赋值
  burger = new Burger();
  rapper = new Rapper();
  skater = new Skater();
  muppie = new Muppie();
  gamer = new Gamer();
  kitchen = new Kitchen();
  chef = new Chef();
})()

export function addAssets(scene){
    kitchen.add(scene);
    chef.add(scene);
    burger.add(scene);
    rapper.add(scene);
    skater.add(scene);
    muppie.add(scene);
    gamer.add(scene);
}

export function setIronHitbox(){
    const geometry = new THREE.BoxGeometry( .7, .5, .5 );
    const material = new THREE.MeshBasicMaterial( { color: 0xffff00 } );
    const mesh = new THREE.Mesh( geometry, material );
    mesh.position.set(0,1,2.35);
    mesh.scale.set(.7,1,1)
    return mesh;
}

如果其他模块需要依赖这些实例的加载完成状态,可以额外导出一个初始化完成的Promise,方便外部判断加载状态。

内容的提问来源于stack exchange,提问作者Antonio Serrano Martin

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.23 18:54:01