代码之家  ›  专栏  ›  技术社区  ›  SamHecquet

Javascript-Redux操作不连续运行

  •  2
  • SamHecquet  · 技术社区  · 6 年前

    当我需要连续运行两个Redux操作时,我会遇到这种情况。 上下文是用户单击一个预览按钮,我想显示一个加载程序,直到拼图完成生成。

    function mapDispatchToProps(dispatch) {
      return {
        onPreview: () => {
          dispatch(generatePreview());
        },
      };
    }
    

    为了做到这一点,我使用了中间件 redux-thunk 我要执行的操作首先返回 Promise.resolve() 我的第二个动作是 then() :

    export function generatingPreview() {
      return dispatch => {
        dispatch({
          type: GENERATING_PREVIEW,
        });
        return Promise.resolve();
      };
    }
    
    export function generatePreview() {
      return (dispatch, getState) => {
        dispatch(generatingPreview()).then(() => {
          const state = getState();
          const conf = state.getIn(['login', 'conf']).toJS();
          const wordList = state.getIn(['login', 'wordList']);
          try {
            const newPuzzle = Wordfind.newPuzzleLax(wordList, conf);
            dispatch(generatePreviewSuccess(newPuzzle));
          } catch (err) {
            dispatch(generatePreviewError(err.message));
          }
        });
      };
    }
    
    export function generatePreviewError(error) {
      return {
        type: GENERATE_PREVIEW_ERROR,
        error,
      };
    }
    
    export function generatePreviewSuccess(payload) {
      return {
        type: GENERATE_PREVIEW_SUCCESS,
        payload,
      };
    }
    

    不幸的是,加载程序从未出现。当我的组件呈现时,我将加载设置为true,并将其更改!我可以看到日志,但看不到加载程序,组件在操作之前不会真正重新呈现 generatePreviewSuccess() generatePreviewError() 被派遣。这不是装载机的问题,如果我更换 newPuzzleLax 函数通过一个循环,以便有足够的时间看到它,我可以看到它!

    我的理论是这个函数 Wordfind.newPuzzleLax(wordList, conf) 我用来生成拼图的是阻塞操作队列,因为在Chrome Redux工具上,我可以看到第一个操作与第二个操作同时出现: Link to the function .

    enter image description here

    如果我在两个动作之间加上1微秒的延迟,加载程序就会出现。。。但我真的很想知道发生了什么。提前谢谢你。如果有什么帮助的话,我用 react-boilerplate

    我还尝试将生成拼图的函数转换为异步函数,方法是:

    const wordFindAsync = async (wordList, conf) =>
      Wordfind.newPuzzleLax(wordList, conf);
    
    export function generatePreview() {
      return (dispatch, getState) => {
        dispatch(generatingPreview())
          .then(() => {
            const state = getState();
            const conf = state.getIn(['login', 'conf']).toJS();
            const wordList = state.getIn(['login', 'wordList']);
            wordFindAsync(wordList, conf);
          })
          .then(res => dispatch(generatePreviewSuccess(res)))
          .catch(err => {
            dispatch(generatePreviewError(err.message));
          });
      };
    }
    
    1 回复  |  直到 6 年前
        1
  •  0
  •   strider    6 年前

    在你的第二个版本中,你没有从 wordFindAsync(wordList, conf) 回到你原来的承诺链,所以到下一个时候它还没有被解决/等待 then .

    export function generatePreview() {
      return (dispatch, getState) => {
        dispatch(generatingPreview())
          .then(() => {
            const state = getState();
            const conf = state.getIn(['login', 'conf']).toJS();
            const wordList = state.getIn(['login', 'wordList']);
            return wordFindAsync(wordList, conf); // 🌟 return your promise here 
          })
          .then(res => dispatch(generatePreviewSuccess(res)))
          .catch(err => {
            dispatch(generatePreviewError(err.message));
          });
      };
    }
    

    这里有一个简单的例子来演示我所指的行为。

    此操作只需等待1秒,直到日志记录“完成”:

    const waitOneSec = () =>
      new Promise(resolve => {
        console.log("waiting 1 secoond");
        setTimeout(resolve, 1000);
      });
    
    waitOneSec()
      .then(() => {
        waitOneSec(); // Promise not returned
      })
      .then(() => console.log("done"));

    而这一个将等待整整2秒,直到记录“完成”:

    const waitOneSec = () =>
      new Promise(resolve => {
        console.log("waiting 1 secoond");
        setTimeout(resolve, 1000);
      });
    
    waitOneSec()
      .then(() => {
        return waitOneSec(); // 🌟 Promise returned
      })
      .then(() => console.log("done"));

    希望能有所帮助。