当你需要await NextFrame()时

class FrameNotice extends Component {
    private _onNextUpdate!: () => void;

    static inst?: FrameNotice;

    protected start() {
        if (!this._onNextUpdate) {
            this.setNextUpdate();
        }
    }

    setNextUpdate() {
        const next = new Promise<void>(resolve => this._onNextUpdate = resolve);
        FrameNotice._nextUpdate = next;
    }

    protected update() {
        this._onNextUpdate();
        this.setNextUpdate();
    }

    static _nextUpdate = Promise.resolve();

    protected onDestroy(): void {
        delete FrameNotice.inst;
        this._onNextUpdate();
    }
}

export function nextFrame() {
    const scene = director.getScene();
    if (!scene) {
        return new Promise(r => requestAnimationFrame(r));
    }
    if (!FrameNotice.inst) {
        const node = new Node('FrameNotice');
        node.parent = scene;
        FrameNotice.inst = node.addComponent(FrameNotice);
        director.addPersistRootNode(node);
        FrameNotice.inst.setNextUpdate();
    }
    return FrameNotice._nextUpdate;
}
1赞

好像像下面这样也行

this.scheduleOnce(()=>{
// next frame cb
cb();
})

1赞

你这个实现看过去有问题啊。你当前帧如果还没有 update 的话。(比如别的组件先 update,里面触发了等待下一帧的逻辑)然后,你这 update 导致当前帧就 resolve 了

1赞

如果在component内部,还是使用scheduleOnce比较好,省去了await之后判断Node.isValid的麻烦

2赞

你说得对,确实不适合在update回调中使用我这个

是的,我这个主要就是想设计一个在组件外可以调用的工具方法。

可以简单封装一下 setTimeout 或者 requestAnimationFrame:

function wait(timeout = 0) {
    return new Promise(resolve => setTimeout(resolve, timeout));
}

function nextFrame() {
    return new Promise(resolve => requestAnimationFrame(resolve));
}

// test

(async function () {
    console.log(1, performance.now());
    await wait(1000);
    console.log(2, performance.now());
    await nextFrame();
    console.log(3, performance.now());
})();

image image

我自己单独写了个计时器的工具