乐趣区

关于javascript:项目中遇到问题杂记

说说竞态

上面是一个典型的在 class 组件里发申请的例子:

class Article extends Component {
  state = {article: null};
  componentDidMount() {this.fetchData(this.props.id);
  }
  async fetchData(id) {const article = await API.fetchArticle(id);
    this.setState({article});
  }
  // ...
}

你很可能曾经晓得,下面的代码潜伏了一些问题。它并没有解决更新的状况。所以第二个你可能在网上找到的经典例子是上面这样的:

class Article extends Component {
  state = {article: null};
  componentDidMount() {this.fetchData(this.props.id);
  }
 componentDidUpdate(prevProps) {if (prevProps.id !== this.props.id) {this.fetchData(this.props.id); } }  async fetchData(id) {const article = await API.fetchArticle(id);
    this.setState({article});
  }
  // ...
}

这显然好多了!但仍旧有问题。有问题的起因是申请后果返回的程序不能保障统一。比方我先申请 {id: 10},而后更新到 {id: 20},但{id: 20} 的申请更先返回。申请更早但返回更晚的状况会谬误地笼罩状态值。

这被叫做竞态,这在混合了async / await(假如在期待后果返回)和自顶向下数据流的代码中十分典型(props 和 state 可能会在 async 函数调用过程中产生扭转)。

Effects 并没有神奇地解决这个问题,只管它会正告你如果你间接传了一个async 函数给 effect。(咱们会改善这个正告来更好地解释你可能会遇到的这些问题。)

如果你应用的异步形式反对勾销,那太棒了。你能够间接在革除函数中勾销异步申请。

或者,最简略的权宜之计是用一个布尔值来跟踪它:

function Article({id}) {const [article, setArticle] = useState(null);

  useEffect(() => {
 let didCancel = false;
    async function fetchData() {const article = await API.fetchArticle(id);
 if (!didCancel) {setArticle(article);
      }
    }

    fetchData();

 return () => { didCancel = true;};  }, [id]);

  // ...
}
退出移动版