欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Vue中watch清除過期副作用的案例詳解

 更新時間:2023年01月03日 09:19:36   作者:無敵小書包  
在這里就不過多說watch的用法了,這篇文章主要通過案例帶大家了解一下如何清除過期的副作用。文中的示例代碼講解詳細,感興趣的小伙伴可以了解一下

在這里就不過多說watch的用法了,主要了解一下如何清除過期的副作用

通過一個案例來說吧:

一個可搜索的下拉選擇器,用戶第一次進行搜索的時候網(wǎng)速比較慢,請求雖然被服務端正確響應了,但是數(shù)據(jù)一直沒有傳輸?shù)娇蛻舳?,用戶看下拉?shù)據(jù)沒變化 就第二次搜索。第二次搜索之后網(wǎng)速恢復正常了,第二次請求的數(shù)據(jù)很快就客戶端接收且正確渲染;緊接著第一次的數(shù)據(jù)也被客戶端接收且客戶端正確渲染。

這樣就可能存在這樣一種情況,第一次請求,服務端響應了請求但數(shù)據(jù)還沒被客戶端接收的時候,有人修改了數(shù)據(jù);然后用戶又點擊刷新,響應數(shù)據(jù) 很快被客戶端接收且處理,這個時候已經(jīng)渲染的是最新的數(shù)據(jù)了。但是第一次請求的響應數(shù)據(jù)被客戶端接收了,如果渲染的話,就不是最新的數(shù)據(jù)了。 因為第二次請求被成功處理后,第一次的請求就已經(jīng)屬于過期的了。

// 下拉選擇器綁定的數(shù)據(jù)
const queryParams = reactive({
    keyword: ''
})

// 下拉列表渲染的數(shù)據(jù)
const listData = []

// 第幾次搜索
let askNum = 0

// 每次搜索用的事件
const times = [5000, 100] // 第一次一共用了5s   第二次用了0.1s

// 監(jiān)視書的信息
watch(queryParams, async (newV) => {
  // 3.查詢參數(shù)第一次發(fā)生變化,響應很慢需要5s
  // 6.查詢參數(shù)第二次發(fā)生變化,響應非???

  asyncTaskIsExpired(times[askNum++], askNum)
    .then(() => {
      console.log(`第${askNum}個任務執(zhí)行完畢`)
      // 渲染列表數(shù)據(jù)
      renderSelectData()
    })
})

/*
 * @param time // 任務需要的時間
 * @param count // 第幾個任務
 */
function asyncTaskIsExpired(time, count) {
  return new Promise((resolve) => {
    console.log(`第${count}個任務開始了`)
    setTimeout(() => {
      resolve()
    }, time)
  })
}

const changeParams = function (str) {
  queryParams.keyword = str
}

function renderSelectData () {
    // do something
    console.log('渲染數(shù)據(jù)')
}

// 第一次搜索
changeBook('xxx')
// 第一次搜索過了兩秒還沒有返回數(shù)據(jù)
setTimeout(() => {
  // 就開始了第二次搜索
  changeBook('yyy')
}, 2000)

更新后的邏輯:

// watch的第三個參數(shù),可以注冊一個過期回調(diào),當這個副作用函數(shù)的執(zhí)行過期時將標識修改為true
// 換句話說,就是在watch內(nèi)部每次檢測到變化時,在副作用函數(shù)執(zhí)行之前,會先執(zhí)行通過onValidate注冊的回調(diào)
watch(book, async (newV, oldV, onInvalidate) => {
  // 添加一個變量,標識上一次的請求是否過期
  let expired = false // 默認是不過期的
  onInvalidate(() => {
    // 過期時,將expired設置為true
    console.log('副作用函數(shù)已過期')
    expired = true
  })
  // asyncTask(times[askNum++], askNum)
  asyncTaskIsExpired(times[askNum++], askNum)
    .then(() => {
      if (!expired) {
        console.log(`第${askNum}個任務執(zhí)行完畢`)
        renderSelectData()
      }
    })
})

更新后執(zhí)行流程就是: 第一次搜索數(shù)據(jù)一直沒有返回,用戶就進行第二次搜索,第二次搜索很快就響應了,客戶端在處理第二次搜索響應的數(shù)據(jù)之前,先將上一次的expired修改 為true,表示上一次請求已經(jīng)過期,上一次請求即使成功(同時發(fā)起多個請求的時候),也不會執(zhí)行后續(xù)操作了。

前面為什么說是“上一次的expired”呢,看上面代碼,expired實際上是存在于一個閉包中的,因此修改expired不會影響到本次請求。

onInvalidate的實現(xiàn)

// 遞歸讀取對象中的數(shù)據(jù)(讓對象中的所有key都有對應副作用函數(shù))
// 從而保證修改響應式對象的任意屬性watch都能監(jiān)聽得到然后執(zhí)行副作用函數(shù)
function traverse (value, seen = new Set()) {
    // 如果要讀取的數(shù)據(jù)是原始值或者已經(jīng)讀取過了,那么什么都不做
    if (typeof value !== 'object' || value !== null || seen.has(value)) return
    // 將數(shù)據(jù)添加到seen中,待變遍歷地讀取過了,避免循環(huán)引用引起的死循環(huán)
    seen.add(value)
    // 假設value是一個對象,使用for-in讀取對象的每一個值,并遞歸調(diào)用traverse進行處理
    for (const key in value) {
        traverse(value[k], seen)
    }
}

function watch (source, cb, options) {
    let getter
    if (typeof source === 'function') {
        getter = source
    } else {
        // 如果watch監(jiān)聽的是一個對象,讀取對象的所有屬性
        getter = () => traverse(source)
    }

    let oldValue, newValue
    // cleanup用來存儲用戶注冊的過期回調(diào)
    let cleanup
    function onInvalidate(fn) {
        // 過期回調(diào)保存到cleanup中
        cleanup = fn
    }

    const job = () => {
        newValue = effectFn()
        // 調(diào)用回調(diào)函數(shù)cb之前,如果有國企的回調(diào)就先調(diào)用過期回調(diào)
        if (cleanup) {
            cleanup()
        }
        // 將 onInvalidate 作為回調(diào)函數(shù)的第三個參數(shù),以邊用戶使用
        cb(newValue, oldValue, onInvalidate)
        oldValue = newValue
    }

    const effectFn = effect(
        () => getter,
        {
            lazy: true,
            scheduler: () => {
                if (options.flush === 'post') {
                    const p = new Promise()
                    p.then(job)
                } else {
                    job()
                }
            }
        }
    )
}

這里 onInvalidate 實際上起到傳遞過期回調(diào)的作用。將程序本身應該處理的邏輯加入到了vue中(類似插件系統(tǒng))。

到此這篇關于Vue中watch清除過期副作用的案例詳解的文章就介紹到這了,更多相關Vue watch清除過期副作用內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!

相關文章

  • 淺談Vue下使用百度地圖的簡易方法

    淺談Vue下使用百度地圖的簡易方法

    本篇文章主要介紹了淺談Vue下使用百度地圖的簡易方法,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2018-03-03
  • vue+openlayer5獲取當前鼠標滑過的坐標實現(xiàn)方法

    vue+openlayer5獲取當前鼠標滑過的坐標實現(xiàn)方法

    在vue項目中怎么獲取當前鼠標劃過的坐標呢?下面通過本文給大家分享實現(xiàn)步驟,感興趣的朋友跟隨小編一起看看吧
    2021-11-11
  • 淺析vue中的provide / inject 有什么用處

    淺析vue中的provide / inject 有什么用處

    這篇文章主要介紹了vue中的provide / inject 有什么用處,非常不錯,具有一定的參考借鑒價值,需要的朋友可以參考下
    2019-11-11
  • vue實現(xiàn)側邊定位欄

    vue實現(xiàn)側邊定位欄

    這篇文章主要為大家詳細介紹了vue實現(xiàn)側邊定位欄,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2022-07-07
  • vue如何動態(tài)修改$router參數(shù)

    vue如何動態(tài)修改$router參數(shù)

    這篇文章主要介紹了vue如何動態(tài)修改$router參數(shù),具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2022-09-09
  • VsCode里的Vue模板的實現(xiàn)

    VsCode里的Vue模板的實現(xiàn)

    這篇文章主要介紹了VsCode里的Vue模板的實現(xiàn),文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2020-08-08
  • element-ui?tree?手動展開功能實現(xiàn)(異步樹也可以)

    element-ui?tree?手動展開功能實現(xiàn)(異步樹也可以)

    這篇文章主要介紹了element-ui?tree?手動進行展開(異步樹也可以),項目中用到了vue的element-ui框架,用到了el-tree組件,需要的朋友可以參考下
    2022-08-08
  • vue?調(diào)用瀏覽器攝像頭實現(xiàn)及原理解析

    vue?調(diào)用瀏覽器攝像頭實現(xiàn)及原理解析

    這篇文章主要為大家介紹了vue調(diào)用瀏覽器攝像頭實現(xiàn)及原理解析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2023-06-06
  • 深入探討Vue3實現(xiàn)多數(shù)據(jù)變化監(jiān)聽的方式

    深入探討Vue3實現(xiàn)多數(shù)據(jù)變化監(jiān)聽的方式

    隨著 Vue 3 的發(fā)布,框架帶來了更多的新特性和增強,其中之一就是 watch 函數(shù)的升級,這一改進使得多個數(shù)據(jù)的變化偵聽更加優(yōu)雅和靈活,本文將深入探討 Vue 3 中的 watch 函數(shù),以及如何以更加優(yōu)雅的方式實現(xiàn)對多個數(shù)據(jù)變化的監(jiān)聽
    2023-08-08
  • Vue3?$emit用法指南(含選項API、組合API及?setup?語法糖)

    Vue3?$emit用法指南(含選項API、組合API及?setup?語法糖)

    這篇文章主要介紹了Vue3?$emit用法指南,使用?emit,我們可以觸發(fā)事件并將數(shù)據(jù)傳遞到組件的層次結構中,本文通過實例代碼給大家介紹的非常詳細,需要的朋友可以參考下
    2022-07-07

最新評論