gpt4 book ai didi

javascript - createAsyncThunk : abort previous request

转载 作者:行者123 更新时间:2023-12-04 08:38:50 31 4
gpt4 key购买 nike

我正在使用 createAsyncThunk向某些 API 发出异步请求。在任何给定时刻,只有一个请求处于事件状态。
我知道可以使用提供的 AbortSignal 中止请求如果我从上一次调用中返回了 Promise。问题是,thunk 本身能否以某种方式“自主”中止先前的请求?
我正在考虑两种选择:

  • 保持状态中的最后一个 AbortSignal。似乎错了,因为状态应该是可序列化的。
  • 将最后一个 Promise 及其 AbortSignal 保留在全局变量中。似乎也错了,因为,你知道,全局变量。

  • 有任何想法吗?谢谢你。

    最佳答案

    我不知道您的特定 api 是如何工作的,但下面是一个工作示例,说明如何将中止逻辑放入操作和 reducer 中,当进行新的提取时,它将中止任何先前事件的假提取:

    import * as React from 'react';
    import ReactDOM from 'react-dom';
    import {
    createStore,
    applyMiddleware,
    compose,
    } from 'redux';
    import {
    Provider,
    useDispatch,
    useSelector,
    } from 'react-redux';
    import {
    createAsyncThunk,
    createSlice,
    } from '@reduxjs/toolkit';

    const initialState = {
    entities: [],
    };
    // constant value to reject with if aborted
    const ABORT = 'ABORT';
    // fake signal constructor
    function Signal() {
    this.listener = () => undefined;
    this.abort = function () {
    this.listener();
    };
    }
    const fakeFetch = (signal, result, time) =>
    new Promise((resolve, reject) => {
    const timer = setTimeout(() => resolve(result), time);
    signal.listener = () => {
    clearTimeout(timer);
    reject(ABORT);
    };
    });
    // will abort previous active request if there is one
    const latest = (fn) => {
    let previous = false;
    return (signal, result, time) => {
    if (previous) {
    previous.abort();
    }
    previous = signal;
    return fn(signal, result, time).finally(() => {
    //reset previous
    previous = false;
    });
    };
    };
    // fake fetch that will abort previous active is there is one
    const latestFakeFetch = latest(fakeFetch);

    const fetchUserById = createAsyncThunk(
    'users/fetchByIdStatus',
    async ({ id, time }) => {
    const response = await latestFakeFetch(
    new Signal(),
    id,
    time
    );
    return response;
    }
    );
    const usersSlice = createSlice({
    name: 'users',
    initialState: { entities: [], loading: 'idle' },
    reducers: {},
    extraReducers: {
    [fetchUserById.fulfilled]: (state, action) => {
    state.entities.push(action.payload);
    },
    [fetchUserById.rejected]: (state, action) => {
    if (action?.error?.message === ABORT) {
    //do nothing
    }
    },
    },
    });

    const reducer = usersSlice.reducer;
    //creating store with redux dev tools
    const composeEnhancers =
    window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__ || compose;
    const store = createStore(
    reducer,
    initialState,
    composeEnhancers(
    applyMiddleware(
    ({ dispatch, getState }) => (next) => (action) =>
    typeof action === 'function'
    ? action(dispatch, getState)
    : next(action)
    )
    )
    );
    const App = () => {
    const dispatch = useDispatch();
    React.useEffect(() => {
    //this will be aborted as soon as the next request is made
    dispatch(
    fetchUserById({ id: 'will abort', time: 200 })
    );
    dispatch(fetchUserById({ id: 'ok', time: 100 }));
    }, [dispatch]);
    return 'hello';
    };

    ReactDOM.render(
    <Provider store={store}>
    <App />
    </Provider>,
    document.getElementById('root')
    );
    如果您只需要解决最新请求的 promise ,而无需中止或取消正在进行的 promise (如果不是最新的,则忽略解决),那么您可以执行以下操作:
    const REPLACED_BY_NEWER = 'REPLACED_BY_NEWER';
    const resolveLatest = (fn) => {
    const shared = {};
    return (...args) => {
    //set shared.current to a unique object reference
    const current = {};
    shared.current = current;
    fn(...args).then((resolve) => {
    //see if object reference has changed
    // if so it was replaced by a newer one
    if (shared.current !== current) {
    return Promise.reject(REPLACED_BY_NEWER);
    }
    return resolve;
    });
    };
    };
    它的使用方式在 this 中演示。回答

    关于javascript - createAsyncThunk : abort previous request,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/64661739/

    31 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com