如何处理 Next.js 中的长时间异步操作以避免页面加载缓慢?

How to handle long async operations in Next.js to avoid slow page loading?

在使用 next-redux-wrapper 时,我如何启动一个长异步任务,以便它在客户端上仅 运行s?我不想在服务器端使用 await,因为它会延迟初始页面加载。我宁愿在任务开始时设置一个加载标志,并在任务完成之前显示一个加载指示器。

假设我的异步操作是这样的:

function async takesLong(store) {
    store.dispatch({type: “LOADING”, payload: true});
    const result = await longOperation();  
    store.dispatch({type: “SETDATA”}, payload: data);
    return store.dispatch({type: “LOADING”, payload: false});
}

我可以在下一页的 getInitialProps 函数中这样调用它:

MyPage.getInitialProps = async ({ store, isServer }) => {
  const loader = takesLong(store)
  if (isServer) await loader;   // <-- will delay client response
  return {
    someprop: "some value"
  };
};

如果页面在客户端 上加载,此方法效果很好。操作开始,我的页面可以显示加载微调器,直到操作完成。但是当在 服务器端 启动时,我在页面显示之前有很长的延迟。我已经尝试了多种方法,但找不到一种能正常工作的方法:

  1. 在服务器上启动进程并且不使用 await 呈现页面而没有将结果写入商店,因此它只在商店中将“loading”设置为 true 而它永远不会获取数据.
  2. 在我的 props 中传递 store 不起作用 - 它最终成为客户端中的空对象 ({ })。
  3. 尝试在我的组件中 运行 它似乎不起作用,原因如下:

    a) 我在 React 组件中没有可访问的 store 对象(仅在 getInitialProps 中不会在客户端调用)。

    b) 即使我在组件中使用动作而不是 store.dispatch,我什么时候可以安全地调用它?我不能在 render 期间执行此操作,因为它会更改 Redux 状态,并且 componentWillReceiveProps 不会在第一个客户端 render

    [=50 之前被调用=]

在使用 Next 时是否有明确定义的模式来将长时间操作推迟到客户端?

componentDidMount 上执行长时间的异步任务,它将 运行 仅在客户端执行。 在 SSR 中做出反应,而不是 运行s componentDidMount 生命周期钩子。

componentDidMount 期间使用绑定操作有效。感谢@eenagy 的建议。按照这个顺序做事情似乎是在做需要做的事情:

import { bindActionCreators } from "redux";
import { setLoading, setError, setData } from "../actions";

componentDidMount() {
  if (!this.props.haveData && !this.props.loading && !this.props.error) {
    this.props.setLoading(true);
    loadSomeData()        // <-- this takes a while to complete
      .then( data => {
        this.props.setData(data);
        this.props.setLoading(false);
      })
      .catch( err => {
        this.props.setError(err);
        this.props.setLoading(false);
      });
  }
}

render() {
  if (this.props.loading) return (<Loading/>);
  return (/*regular page*/);
}

export const mapDispatchToProps = dispatch => {
  return bindActionCreators({ setLoading, setError, setData }, dispatch);
};

export default connect(mapStateToProps, mapDispatchToProps)(Component);

这样,如果初始数据尚未加载(比如由另一个页面加载),它将在 组件挂载和 运行 异步直到操作完成并且 调用 redux 中的操作使页面变为 re-render.