如何在 Saga 中重新调度操作,如 redux 工具包自动重新获取

问题描述 投票:0回答:1

我正在尝试实现 redux-saga 操作调度功能,例如 redux 工具包中的自动重新获取。

打开应用程序时,我调度一些操作来从服务器获取数据并更新 redux 存储。当用户停留在后台并重新进入应用程序时,根据用户保持不活动状态的时间,应用程序将重新调度操作以再次从服务器获取数据。我可以在每次从服务器获取数据时保存时间戳,并比较从非活动状态切换到活动状态的时间。但如果有一个已经做好的功能,我肯定会想使用它!

redux redux-toolkit redux-saga
1个回答
0
投票

有一些库,如 saga-query 可以为你做与 rtk-query 类似的事情,但据我所知,这个库具体不支持开箱即用的重新获取焦点。

没有任何lib,可以这样实现:

import {delay, put, call, takeEvery, takeLeading, fork} from 'redux-saga/effects';

// Utility function to create a channel that will receive a message
// every time visibility changes
const createVisibilityChannel = () => {
    return eventChannel((emit) => {
        const handler = () => void emit(!document.hidden);
        document.addEventListener('visibilitychange', handler);
        return () => document.removeEventListener('visibilitychange', handler);
    });
};

// Works as takeLeading except it ignores actions for extra additional time
const takeLeadingWithDelay = (ms, pattern, saga, ...args) => {
    return takeLeading(pattern, function* (action) {
        yield call(saga, ...args, action);
        yield delay(ms);
    });
};

// Root saga
function* appSaga() {
    // Creates visbility channel
    const visibilityChannel = yield call(createVisibilityChannel);

    // Limits time between refetches for 1 minute
    yield takeLeadingWithDelay(60000, 'FETCH_DATA', fetchData);
    
    // Dispatches fetch action every time page becomes visible
    yield takeEvery(visibilityChannel, function* (visible) {
        if (visible) yield put({type: 'FETCH_DATA'});
    });

    // Fetches data on app start and starts the first timer
    yield put({type: 'FETCH_DATA'})
}

// Example fetching function
function* fetchData() {
    const response = yield fetch(
        'https://api.spacexdata.com/v3/launches?limit=5',
    );
    const data = yield response.json();
    console.log({data});
}

此解决方案假设延迟计时器并非特定于页面模糊/焦点,而是特定于页面模糊/焦点的任何重新获取,包括页面焦点上的重新获取,因为在相反的情况下,我不确定当用户切换到时计时器的逻辑应该是什么页面太早了。

© www.soinside.com 2019 - 2024. All rights reserved.