[开发者心得] [心得分享] Promise使用心得

[复制链接]
1135 |3
剑寂万古 发表于 2023-5-4 13:24:42 | 显示全部楼层 |阅读模式
功能介绍

    Promise 是js中进行异步编程的解决方案,可以灵活指定回调方法,支持链式调用.使用promise可以方便的实现一些功能:比如 分帧加载,异步等待,等功能

   
Promise 的构造函数接收一个函数为参数,并且传入两个参数:resolve,reject,分别表示异步操作执行成功后的回调函数和异步操作执行失败后的回调函数.Promise 的状态只有三种,且只能改变一次
    pending -->  resolved  `[成功后调用]`
    pending -->  rejected  `[失败后调用]`

快速使用

// promise
        new Promise((resolve, reject) => {
            console.log("promise 开始执行代码,当前为同步实现");// 1
            // 异步方法
            setTimeout(() => {
                console.log("promise setTimeout 执行代码,经过了一帧的等待");// 3
                resolve(null);
                console.log("promise resolve之后的代码,会在回调前执行");// 4
            }, 0);
        }).then(() => {
            console.log("promise 结束后执行then代码回调");// 5
        }).catch((e) => {
            console.log("promise 执行出现错误catch错误:" + e);// error
        });
        console.log("promise 代码段后顺序执行的代码");// 2


一些Tips
  
    - then会在整个函数调用完之后执行
    - 不可以重复调用resolve
    - reject是一种特殊的resolve,也不可一起调用(在内部.catch() 方法用来捕获与处理错误 ,相当于 then(undefined, onRejected);)
    - promise 的 then()返回一个新的 promise, 可以开成 then()的链式调用
    - 当使用 promise 的 then 链式调用时, 可以在最后指定失败的回调,前面任何操作出了异常, 都会传到最后失败的回调中处理


进阶用法


Promise.all 方法:
说明:只有所有的 promise 都成功才成功, 只要有一个失败了就直接失败;
返回一个新的 promise(成功的时候返回的是一个结果数组,而失败的时候则返回最先被reject失败状态的值)
`Promise.all(promises) => {} `

Promise.race 方法:
说明:第一个完成的 promise 就是最终的结果状态;返回一个新的 promise
`Promise.race(promises) => {} `

拓展方法:


/*
* @Author: chen.liang
* @Date: 2023-05-04 13:04:30
* @FilePath: \promiseTest\JavaScripts\TimeUtilEx.ts
*/

export namespace TimeUtilEx {

    /**
     * 分帧加载
     */
    export class WaitSpawn {
        /**
         * 每帧加载个数
         */
        public static spawnCount: number = 100;
        private static _instance: WaitSpawn;
        /**
         * 生成物体
         * @param spawnInfo 生成信息
         * @returns
         */
        public static spawn(spawnInfo: SpawnInfo): Promise<Gameplay.GameObject> {
            if (!this._instance) {
                this._instance = new WaitSpawn();
            }
            return this._instance.addSpawn(spawnInfo);
        }
        constructor() {
            TimeUtil.onEnterFrame.add(this.onEnterFrame.bind(this));
        }
        /**
         * 等待列表
         */
        private _waitList: { spawnInfo: SpawnInfo, resolve }[] = [];
        /**
         * 添加异步生成物体
         * @param spawnInfo
         * @returns
         */
        private addSpawn(spawnInfo: SpawnInfo) {
            return new Promise<Gameplay.GameObject>((resolve) => this._waitList.push({ spawnInfo: spawnInfo, resolve: resolve }));
        }
        /**
         * 每帧执行
         * @param dt
         * @returns
         */
        private onEnterFrame(dt: number) {
            console.log("frame time:", dt)
            if (dt >= 100) return;
            for (let index = 0; index < WaitSpawn.spawnCount && this._waitList.length > 0; index++) {
                const waitData = this._waitList.shift();
                Gameplay.GameObject.asyncSpawn(waitData.spawnInfo).then(async (go) => {
                    await go.ready();
                    waitData.resolve(go);
                });
            }
        }
    }

    /**
     *  异步等待
     */
    export class WaitReady {

        /** 是否有执行 */
        public padded: boolean = false;
        /** 执行中时,缓存异步回调 */
        protected actionList: { resolve: (b) => void, reject: (b) => void }[] = [];

        /**
         * 异步执行
         */
        public async ready(): Promise<null> {
            if (this.padded) {
                return null;
            }
            return new Promise((resolve, reject) => {
                this.actionList.push({ resolve: resolve, reject: reject });
            });
        }

        /**
         * 调用结束结束
         * @description 仅支持了成功调用
         */
        public over(): void {
            if (this.padded) {
                return;
            }
            this.padded = true;
            let ls = this.actionList, len = ls.length;
            for (let i = 0; i < len; i++) {
                ls[i].resolve(null);
            }
            this.actionList = [];
        }

    }
}




回复

使用道具 举报

喵喵哭唧唧 发表于 2023-5-4 13:34:35 | 显示全部楼层
请问能举一些使用案例么,比如分帧处理逻辑之类的
回复

使用道具 举报

剑寂万古楼主 发表于 2023-5-4 14:09:01 | 显示全部楼层
喵喵哭唧唧 发表于 2023-5-4 13:34
请问能举一些使用案例么,比如分帧处理逻辑之类的

写在拓展方法中的
回复

使用道具 举报

喵喵哭唧唧 发表于 2023-5-4 14:38:43 | 显示全部楼层
剑寂万古 发表于 2023-5-4 14:09
写在拓展方法中的

请问是否还有其它的应用场景可以介绍么
回复

使用道具 举报

热门版块
快速回复 返回顶部 返回列表