触发请求,然后执行操作,然后执行其他请求和操作

时间:2019-03-28 11:06:58

标签: redux rxjs redux-observable

刚开始学习RxJS并喜欢它,但是有一个我无法解决的问题。

它如何工作:您可以按关键字搜索。但是首先应将关键字发送到服务器进行分析,然后将分析结果存储在商店中,然后将分析结果用于搜索查询。

我已经找到了如何获取和保存关键字分析结果以及如何发送搜索请求的方法,但是找不到如何结合使用。对我来说,主要问题是如何检查商店中是否已有关键字,然后仅跳过第一部分并发送搜索请求。

const initialState = {
    keywords: {}, // keywords cache
    query: [], // current query
    items: [], // search result
    error: null,
};

const reducers = {
    setQuery: (state, { payload }) => {
        state.query = payload;
    },

    setItems: (state, { payload }) => {
        state.items = payload;
    },

    setError: (state, { payload }) => {
        state.error = payload;
    },

    addKeyword: (state, { payload }) => {
        state.keywords[payload.keyword] = payload;
    },
};

const search = createSlice({
    initialState,
    reducers,
});

const { actions } = search;

const setQueryEpic = (action$, state$) => action$.pipe(
    ofType(actions.setQuery.type),
    // This part is skipped if all keywords already in state
    flatMap(({ payload }) => payload),
    filter(keyword => !state$.value.keywords[keyword]),
    mergeMap(
        keyword => ajax
            .getJSON(`/analyze/keyword?keyword=${keyword}`),
    ),
    map(keywordData => actions.addKeyword(keywordData)),
    // This part does request and set search result. Should wait for keywords analyze
    switchMap((action) => {
        const state = state$.value
        const params = {
            keywords_vectors: state.query.map(queryKeywords => state.keywords[queryKeywords].vector),
        };
        return ajax
            .post(`/search`, JSON.stringify(params))
            .pipe(
                map(data => data.response.items),
            );
    }),
    map(items => actions.setItems(items)),
    catchError(error => of(actions.setError(error.message))),
);

更新:找到了此解决方案

const setQueryEpic = (action$, state$) => action$.pipe(
    ofType(actions.setQuery.type),
    flatMap(({ payload }) => {
        const requests = payload.map((keyword) => {
            if (state$.value.keywords[keyword]) {
                // keyword in cache
                return of(state$.value.keywords[keyword]);
            }
            // analyze new keyword
            return ajax
                .getJSON(`/analyze/keyword?keyword=${keyword}`)
        });
        // wait for all requests
        return forkJoin(requests);
    }),
    switchMap((keywords) => {
        const params = {
            keywords_vectors: keywords.map(data => data.vector),
        };
        // create actions to add keywords to cache
        const addKeywordActions = keywords
            .filter(data => !state$.value.keywords[data.keyword])
            .map(data => actions.addKeyword(data));

        return ajax
            .post(`/search`, JSON.stringify(params))
            .pipe(
                map(data => data.response.items),
                // combine all actions
                map(items => [actions.setItems(items), ...addKeywordActions]),
            );
    }),
    flatMap(action => action),
    catchError(error => of(actions.setError(error.message))),
);

但是我不喜欢从外部作用域获取addKeywordActions,如果您发送的搜索请求很少,switchMap会重置所有链接。保留关键字数据会很好

0 个答案:

没有答案