最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

一文帶你簡(jiǎn)單封裝JS下的異步任務(wù)對(duì)象

 更新時(shí)間:2022年11月17日 10:43:47   作者:頭疼腦脹的代碼搬運(yùn)工  
我們?cè)跓倪^(guò)程中去干了別的事情,就屬于異步模式,異步模式中不會(huì)等待異步任務(wù)的結(jié)束才開始執(zhí)行下一個(gè)同步的任務(wù),都是開啟過(guò)后就立即執(zhí)行下一個(gè)任務(wù),下面這篇文章主要給大家介紹了如何通過(guò)一文帶你簡(jiǎn)單封裝JS下的異步任務(wù)對(duì)象的相關(guān)資料,需要的朋友可以參考下

廢話開篇:

js有微任務(wù)跟宏任務(wù),但是不管是哪種任務(wù)并不代表著會(huì)開辟新的線程,可以理解為將上述兩種任務(wù)放到“主任務(wù)”之后執(zhí)行,有點(diǎn)像iOS下的在主線程調(diào)用異步函數(shù)一樣,其實(shí)也只是將異步任務(wù)降低了優(yōu)先級(jí),等主線程不忙的時(shí)候再處理該任務(wù),比如:UI任務(wù)優(yōu)先級(jí)較高,所以,任何的主線程下的異步任務(wù)都要排到UI任務(wù)結(jié)束之后進(jìn)行。

一、利用 Promise 實(shí)現(xiàn)異步任務(wù)

利用 Promise 實(shí)現(xiàn)異步任務(wù),如果不加任何限制,微任務(wù)的執(zhí)行便會(huì)按添加的先后順序進(jìn)行執(zhí)行。這里簡(jiǎn)單封裝一下,實(shí)現(xiàn)微任務(wù)下的執(zhí)行依賴??赡苡腥藭?huì)問(wèn),await 不就行了嗎?是的,聲明異步方法就能滿足,順序執(zhí)行。但是還是要整理一個(gè)過(guò)程來(lái)增加對(duì)代碼的理解。

二、實(shí)現(xiàn)效果

這里簡(jiǎn)單的邏輯是:異步3任務(wù) -> 異步2任務(wù) -> 異步1任務(wù)

三、代碼實(shí)現(xiàn)

下面是調(diào)度代碼邏輯

function dispath(){
    console.log('異步3完成,異步2才能開始,異步2完成,異步1才能開始')
    //創(chuàng)建任務(wù)一
    let blockOperationOne = new BlockOperation((b)=>{
        console.log('異步1任務(wù)');
        //單一任務(wù)完成事件通知
        b.finished();
    });

    //添加新任務(wù)
    blockOperationOne.addExecutionBlock((b)=>{
        console.log('異步1新增任務(wù)');
        b.finished();
    });

    //創(chuàng)建任務(wù)二
    let blockOperationTwo = new BlockOperation((b)=>{
        console.log('異步2任務(wù)');
        b.finished();
    });

    blockOperationTwo.addExecutionBlock((b)=>{
        console.log('異步2新增任務(wù)2');
        b.finished();
    });

    blockOperationTwo.addExecutionBlock((b)=>{
        console.log('異步2新增任務(wù)需要等待4秒');
        setTimeout(() => {
            console.log('異步2新增任務(wù)3');
            b.finished();
        }, 4000);
    });

    //創(chuàng)建任務(wù)三
    let blockOperationThree = new BlockOperation((b)=>{
        console.log('異步3需要等待1秒');
        setTimeout(() => {
            console.log('異步3任務(wù)');
            b.finished();
        }, 1000);
    });

    //添加依賴
    blockOperationOne.addDependency(blockOperationTwo);
    blockOperationTwo.addDependency(blockOperationThree);

    //開始執(zhí)行
    blockOperationOne.start();
    blockOperationTwo.start();
    blockOperationThree.start();

    console.log('我是宏任務(wù)');
};

下面是封裝的 BlockOperation 對(duì)象

//任務(wù)通知對(duì)象
class Block{
    //完成回調(diào)
    doneCallBack = null
    constructor(doneCallBack){
        this.doneCallBack = doneCallBack
    }

    //單任務(wù)完成
    finished(){
        this.doneCallBack();
    }
}

//任務(wù)對(duì)象
class BlockOperation {
    //任務(wù)集合
    blocks = []
    //是否已開始
    isBeginStart = false
    //依賴任務(wù)對(duì)象
    dependencyOperation = null
    //被依賴影響的對(duì)象
    impactOperation = null
    //全部完成的事件判定
    allOperationIsDone = false
    //全部完成的事件回調(diào)
    allOperationDoneBlock = ()=>{
        //將依賴任務(wù)完成進(jìn)行自身任務(wù)
        if(this.impactOperation){
            this.impactOperation.start()
        }
    };

    //代理
    proxy = null;
    //代理set方法
    handler = {
        set(target,property,value){
            target[property] = value
            if(property == 'allOperationIsDone' && value){
                //執(zhí)行閉包回調(diào)
                target.allOperationDoneBlock();
            }
            return true
         },
        get(target,property){
            return target[property]
        }
    }

    //初始化
    constructor(cb){
        this.blocks.push(cb)
        this.addObserver()
    }

    //添加觀察者
    addObserver(){
        this.proxy = new Proxy(this, this.handler)
    }

    //添加新任務(wù)
    addExecutionBlock(cb){
        this.blocks.push(cb)
    }
    
    //添加依賴
    addDependency(blockOperation){
        this.dependencyOperation = blockOperation
        blockOperation.impactOperation = this
    }

    //開始異步任務(wù)
    start(){
        const self = this
        self.isBeginStart = true
        //先判斷是否有依賴
        if(this.dependencyOperation && this.dependencyOperation.allOperationIsDone == false){
            //這里加一個(gè)定時(shí)器(目的是添加一個(gè)相對(duì)靠后的宏任務(wù)來(lái)檢查所有的任務(wù)是否都執(zhí)行了開啟,不是很嚴(yán)謹(jǐn))
            setTimeout(()=>{
                if(self.dependencyOperation.isBeginStart == false){
                    throw Error('請(qǐng)檢查是否有依賴任務(wù)未開啟')
                }
            },0)
            //等待依賴的執(zhí)行完
            return
        }
        self.blocks.forEach((operationBlock) => {
            Promise.resolve(operationBlock).then((res)=>{
                if(res){
                    res(new Block(()=>{
                        //刪除任務(wù)
                        delete self.blocks[self.blocks.indexOf(res)]
                        //過(guò)濾null(防止delete執(zhí)行后數(shù)組中有null占位)
                        self.blocks = self.blocks.filter((item) => {
                            return item
                        })
                        //判斷是否全部完成
                        self.proxy.allOperationIsDone = (self.blocks.length == 0)
                    }))
                };
            })
        });
    }
}

四、總結(jié)與思考

其實(shí) async / await 的使用是可以避免回調(diào)的,但是,這里并不是去用它的特性來(lái)優(yōu)化代碼,而是用 Promisethen 函數(shù)是微任務(wù)來(lái)處理異步,目的就是將一些不太重要的邏輯放到主任務(wù)之后,這里也是參考了 iOS 下的 NSBlockOperation 的一些 api 命名,語(yǔ)言間實(shí)現(xiàn)代碼雖然不同,但卻存在著互通的設(shè)計(jì)思路吧。

到此這篇關(guān)于封裝JS下異步任務(wù)對(duì)象的文章就介紹到這了,更多相關(guān)JS異步任務(wù)對(duì)象封裝內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • IE6-IE9中tbody的innerHTML不能賦值的解決方法

    IE6-IE9中tbody的innerHTML不能賦值的解決方法

    這篇文章主要介紹了IE6-IE9中tbody的innerHTML不能賦值的解決方法,需要的朋友可以參考下
    2014-06-06
  • 微信小程序?qū)崿F(xiàn)驗(yàn)證碼獲取倒計(jì)時(shí)效果

    微信小程序?qū)崿F(xiàn)驗(yàn)證碼獲取倒計(jì)時(shí)效果

    這篇文章主要為大家詳細(xì)介紹了微信小程序?qū)崿F(xiàn)驗(yàn)證碼獲取倒計(jì)時(shí)效果,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2018-02-02
  • 淺談javascript語(yǔ)法和定時(shí)函數(shù)

    淺談javascript語(yǔ)法和定時(shí)函數(shù)

    初學(xué)者可能對(duì)Javascript的定時(shí)器有誤解,認(rèn)為它們是線程,其實(shí)Javascript是運(yùn)行于單線程中的,而定時(shí)器僅僅是計(jì)劃在未來(lái)的某個(gè)時(shí)間執(zhí)行,而具體的執(zhí)行時(shí)間是不能保證的,因?yàn)樵陧?yè)面的生命周期中,不同的時(shí)間可能有其它代碼在控制Javascript的里進(jìn)程。
    2015-05-05
  • JavaScript中統(tǒng)計(jì)Textarea字?jǐn)?shù)并提示還能輸入的字符

    JavaScript中統(tǒng)計(jì)Textarea字?jǐn)?shù)并提示還能輸入的字符

    是在文本框中輸入文字的時(shí)候,會(huì)自動(dòng)統(tǒng)計(jì)輸入的字符,并顯示用戶還能輸入的字符,其實(shí)js也可以實(shí)現(xiàn),下面就以示例的方式為大家講解下
    2014-06-06
  • Electron實(shí)現(xiàn)應(yīng)用打包、自動(dòng)升級(jí)過(guò)程解析

    Electron實(shí)現(xiàn)應(yīng)用打包、自動(dòng)升級(jí)過(guò)程解析

    這篇文章主要介紹了Electron實(shí)現(xiàn)應(yīng)用打包、自動(dòng)升級(jí)過(guò)程解析,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2020-07-07
  • js實(shí)現(xiàn)簡(jiǎn)單貪吃蛇游戲

    js實(shí)現(xiàn)簡(jiǎn)單貪吃蛇游戲

    這篇文章主要為大家詳細(xì)介紹了js實(shí)現(xiàn)簡(jiǎn)單貪吃蛇游戲,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2020-05-05
  • 利用iscroll4實(shí)現(xiàn)輪播圖效果實(shí)例代碼

    利用iscroll4實(shí)現(xiàn)輪播圖效果實(shí)例代碼

    iScroll 4 這個(gè)版本完全重寫了iScroll這個(gè)框架的原始代碼。這個(gè)項(xiàng)目的產(chǎn)生完全是因?yàn)橐苿?dòng)版webkit瀏覽器(諸如iPhone,iPad,Android 這些系統(tǒng)上廣泛使用)。下面這篇文章主要介紹了利用iscroll4實(shí)現(xiàn)輪播圖效果的方法教程,需要的朋友可以參考下。
    2017-01-01
  • JavaScript實(shí)現(xiàn)鼠標(biāo)移動(dòng)事件畫筆

    JavaScript實(shí)現(xiàn)鼠標(biāo)移動(dòng)事件畫筆

    這篇文章主要為大家詳細(xì)介紹了JavaScript實(shí)現(xiàn)鼠標(biāo)移動(dòng)事件畫筆,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2022-08-08
  • javascript實(shí)現(xiàn)智能手環(huán)時(shí)間顯示

    javascript實(shí)現(xiàn)智能手環(huán)時(shí)間顯示

    這篇文章主要為大家詳細(xì)介紹了javascript實(shí)現(xiàn)智能手環(huán)時(shí)間顯示,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2020-09-09
  • Js中將Long轉(zhuǎn)換成日期格式的實(shí)現(xiàn)方法

    Js中將Long轉(zhuǎn)換成日期格式的實(shí)現(xiàn)方法

    這篇文章主要介紹了Js中將Long轉(zhuǎn)換成日期格式的實(shí)現(xiàn)方法,非常不錯(cuò),具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2018-06-06

最新評(píng)論

芷江| 江油市| 盖州市| 杭锦后旗| 汝阳县| 昌平区| 天津市| 长宁县| 通州区| 偏关县| 鹰潭市| 阿拉尔市| 仲巴县| 霍林郭勒市| 青阳县| 锡林郭勒盟| 石景山区| 丰台区| 旅游| 阿图什市| 开化县| 汉中市| 六枝特区| 广汉市| 陆良县| 保山市| 井研县| 集贤县| 济阳县| 孙吴县| 固安县| 南开区| 石棉县| 册亨县| 应城市| 宜城市| 社会| 丹阳市| 八宿县| 保康县| 平武县|