【问题标题】:How to perform a fetch before another fetch (React Native)如何在另一个 fetch 之前执行 fetch (React Native)
【发布时间】:2021-07-24 00:23:13
【问题描述】:

我正在用 React Native 开发一个项目。我遇到的问题是所有提取都同时开发,相反我希望一个提取在另一个提取结束之前等待以使用其数据。

然后我想在第二次提取中使用idTitle,但我不能,因为它们是同时执行的

function SongScreen({ route }) {

  const { textArtist, textSong } = route.params;

  const geniusUrl = 'https://api.genius.com';

  const [isLoading, setLoading] = useState(true);

  const [idTitle, setIdTitle] = useState([]);
  const [idVideoYT, setIdVideoYT] = useState([]);
       
  useEffect(async () => {
    fetch(geniusUrl + '/search?q=' + textSong, {
      headers: { 'Authorization': 'Bearer ' + geniusToken }
    })
      .then((response) => response.json())
      .then((json) => {
        for (const value of json.response.hits) {
          if ((value.result.title.toLowerCase() == textSong.toLowerCase()) &&
            (value.result.primary_artist.name.toLowerCase() == textArtist.toLowerCase())) {
            setIdTitle(value.result.api_path)
            setIdArtist(value.result.primary_artist.api_path)
          }
        }
      })
      .catch((error) => { AlertView(), setModalVisible(true) })
      .finally(() => setLoading(false));
  }, []);

          
  useEffect(() => {
    fetch(geniusUrl + idTitle, {
      headers: { 'Authorization': 'Bearer ' + geniusToken }
    })
      .then((response) => response.json())
      .then((json) => {
        for (const value of json.response.song.media) {
          if (value.provider == 'youtube')
            setIdVideoYT(value.url)
        }
      })
      .catch((error) => alert(error)) //{ AlertView(), setModalVisible(true) })
      .finally(() => setLoading(false));
  }, []);
    
  return (
    //.....
  )
}

编辑:我尝试像这样连接,但它一直给出同样的错误:

    useEffect(async () => {
    fetch(geniusUrl + '/search?q=' + textSong, {
      headers: { 'Authorization': 'Bearer ' + geniusToken }
    })
      .then((response) => response.json())
      .then((data) => {
        for (const value of data.response.hits) {
          if ((value.result.title.toLowerCase() == textSong.toLowerCase()) &&
            (value.result.primary_artist.name.toLowerCase() == textArtist.toLowerCase())) {
            setIdTitle(value.result.api_path)   
            setIdArtist(value.result.primary_artist.api_path)   
          }
        }
      })
      .then(
        fetch(geniusUrl + idTitle, {
          headers: { 'Authorization': 'Bearer ' + geniusToken }
        })
          .then((response) => response.json())
          .then((json) => {
            for (const value of json.response.song.media) {
              if (value.provider == 'youtube')
                setIdVideoYT(value.url)
            }
          })
          .catch((error) => alert(error)) //{ AlertView(), setModalVisible(true) })
          .finally(() => setLoading(false))
      )
      .catch((error) => { AlertView(), setModalVisible(true) })
      .finally(() => setLoading(false));
  }, []);

编辑 2:我尝试在 if 中添加 then,但它给出的错误是它找不到 then 变量:

useEffect(async () => {
fetch(geniusUrl + '/search?q=' + textSong, {
  headers: { 'Authorization': 'Bearer ' + geniusToken }
})
  .then((response) => response.json())
  .then((data) => {
    for (const value of data.response.hits) {
      if ((value.result.title.toLowerCase() == textSong.toLowerCase()) &&
        (value.result.primary_artist.name.toLowerCase() == textArtist.toLowerCase())) {
         setIdTitle(value.result.api_path)
         setIdArtist(value.result.primary_artist.api_path)

          then(() => fetch(geniusUrl + value.result.api_path, {
            headers: { 'Authorization': 'Bearer ' + geniusToken }
          })
            .then((response) => response.json())
            .then((json) => {
              for (const value of json.response.song.media) {
                if (value.provider == 'youtube')
                  setIdVideoYT(value.url)
              }
            })
            .catch((error) => alert(error))
            .finally(() => setLoading(false))
          )

      }
    }
  })
  .catch((error) => alert(error))
  .finally(() => setLoading(false));


 }, []);

编辑 3:为方便起见,我在同一个 useEffect 中添加了所有 3 个提取。我尝试使用 await 进行第三次获取,但它总是进入捕获状态。

useEffect(async () => {


fetch(geniusUrl + '/search?q=' + textSong, {
  headers: { 'Authorization': 'Bearer ' + geniusToken }
})
  .then((response) => response.json())
  .then((data) => {
    for (const value of data.response.hits) {
      if ((value.result.title.toLowerCase() == textSong.toLowerCase()) &&
        (value.result.primary_artist.name.toLowerCase() == textArtist.toLowerCase())) {
        setIdTitle(value.result.api_path)   //for third fetch
        setIdArtist(value.result.primary_artist.api_path)  
      }
    }
  })
  .catch((error) => { AlertView(), setModalVisible(true) })
  .finally(() => setLoading(false));


  fetch(lyricsUrl + textArtist + '/' + textSong)
    .then((response) => response.json())
    .then((text) => setDataLyrics(text.lyrics))
    .catch((error) => { AlertView(), setModalVisible(true) })
    .finally(() => setLoadingLyrics(false));


try {
  let response = await fetch(geniusUrl + idTitle, {
    headers: { 'Authorization': 'Bearer ' + geniusToken }
  });
  let id = await response.json();
  for (const value of id.response.song.media) {
    if (value.provider == 'youtube')
      setIdVideoYT(value.url)
  }
}
catch (error) {
  alert(error);
}
setLoading(false);

}, []);

【问题讨论】:

  • 将第二个 fetch 放在第一个 fetch 的 then 回调中。
  • 或使用await,因为您已经将函数标记为async。无需使用 .then 链接,也使您的代码更易于阅读。
  • 要么将两个 fetch 放在同一个效果中,然后将它们链接起来,要么使第二个效果依赖于 idTitle 状态(并且让它仍然为空时什么都不做)。
  • 我应该在哪里添加await? @Mike'Pomax'Kamermans
  • 我也尝试过以相同效果进行连接,但它仍然给我带来了问题。如何让它依赖于 idTitle? @Bergi

标签: javascript react-native async-await promise


【解决方案1】:

由于 React Native 再次是一个基于 JS 的框架,它作为非阻塞模型逐行执行。

所以要解决这个问题! const result = await fetch(URL, payload)

fetch(someUrl, Payload)
.then(res => res.json)
.then(res => {
Do something 
 fetch(someUrl)... etc
})

【讨论】:

    猜你喜欢
    • 2017-07-27
    • 2020-09-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-09-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多