首页 > 解决方案 > 从 API 异步获取的循环中断

问题描述

我正在开发一个 React 项目,其中包括一个可供选择的电影下拉菜单。当我选择一部电影时,它会调用函数filmSelected:

const [selectedFilm, setSelectedFilm] = useState({})

const fetchCharacters = async (l, f) => {
    // loops through list (l) and fetches character info from api
    let c = 0;
    let characters = [];
    for (let i = 0; i < l.length; i++) {
        try {
          const charFetch = await fetch(l[i]);
          const response = await charFetch.json();
          characters.push(response);
          c++;
          setCount(c);
        } catch (e) {
          return e;
        }
      }
    return characters;
  };

const filmSelected = async (film) => {
    // sets the selected film state to the film selected in dropdown menu
    // fetches character info from api
      setSelectedFilm(film)
      const c = await fetchCharacters(film.characters, film);
      setCharacters(c);
  };

如果我在 for 循环完成之前选择另一部电影,它会产生一个问题,并且几乎看起来函数的 for 循环与新调用同时执行。如果电影在 for 循环完全执行之前发生变化,我正在尝试找出一种退出 for 循环的方法。

我正在使用 useState 并在函数中设置 selectedFilm 状态,但它设置的状态不够快,无法检查电影是否通过 fetchCharacters 函数和 selectedFilm 的状态是否相同。

任何建议将不胜感激。先感谢您!

凯文

标签: javascriptreactjsasynchronousstate

解决方案


假设您使用 axios 发出 API 请求。(您可以将这种方法与任何库一起使用,方法可能会有所不同)。

在提出新请求之前,您必须取消先前的请求。

你可以很容易地在 axios 中做到这一点。

// declare an ajax request's cancelToken (globally)
let ajaxRequest = null; 

function getComments() {

    // cancel  previous ajax if exists
    if (ajaxRequest ) {
        ajaxRequest.cancel(); 
    }

    // creates a new token for upcomming ajax (overwrite the previous one)
    ajaxRequest = axios.CancelToken.source();  

    return axios.get('/api/get-comments', { cancelToken: ajaxRequest.token }).then((response) => {
        console.log(response.data)
    }).catch(function(err) {
        if (axios.isCancel(err)) {
           console.log('Previous request canceled, new request is send', err.message);
        } else {
               // handle error
        }
    });
}

有关它的更多详细信息,您可以谷歌 axios 取消令牌或访问


推荐阅读