【发布时间】: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