Spotify API,无法正确链接两个 API 调用
Spotify API, can't chain two API calls properly
我在链接这两个 API 调用时遇到问题。所以基本上我正在尝试重新创建 Spotify 界面并且单独地,这些调用确实有效,这太棒了!
我还有一个 'onPlayClick' 函数,它与 'onNextClick' 的功能基本相同,如下所示,但具有不同的端点,并且是 PUT 方法而不是 POST 方法。正确播放和设置 selectedSong 的状态。
但是,调用 updateCurrentlyPlaying 的 onNextClick 没有按预期工作。预期的功能是当用户单击下一首时,歌曲将转到下一首曲目(有效!),然后更新 UI.
上的曲目信息
但最终发生的是它首先更新曲目信息然后切换曲目,所以在 UI 上它在某种意义上总是 "one track behind" 我不知道为什么第二个 API 领先于第一个! :S 非常感谢任何帮助!
onNextClick = () => {
const { deviceId, token } = this.state
fetch(`https://api.spotify.com/v1/me/player/next?device_id=${deviceId}`, {
method: 'POST',
headers: { 'Authorization': 'Bearer ' + token },
})
.then(response => response.json())
.then(this.updateCurrentlyPlaying())
}
updateCurrentlyPlaying(){
const { deviceId, token } = this.state;
let selectedSong;
fetch(`https://api.spotify.com/v1/me/player/currently-playing?device_id=${deviceId}`, {
method: 'GET',
headers: { 'Authorization': 'Bearer ' + token },
})
.then(response => response.json())
.then(data => {
selectedSong = {
name: data.item.name,
duration: Math.round(data.item.duration_ms / 1000),
artists: data.item.artists,
album: data.item.album.name,
image: data.item.album.images[0],
id: data.item.id,
uri: data.item.uri,
offset: data.offset
}
this.setState({ selectedSong })
})
}
更新答案
如下所述,下面的原始答案可能仍然相关。然而,第一个问题是 this.updateCurrentlyPlaying
的调用方式。在编写 .then(this.updateCurrentlyPlaying())
时,您会立即调用 this.updateCurrentlyPlaying
,这会将 undefined
传回 Promise 链。
相反,你想要这样的东西:
onNextClick = () => {
const { deviceId, token } = this.state
fetch(`https://api.spotify.com/v1/me/player/next?device_id=${deviceId}`, {
method: 'POST',
headers: { 'Authorization': 'Bearer ' + token },
})
.then(() => this.updateCurrentlyPlaying())
}
原答案
我的猜测是您的代码没有问题,但 Spotify 的行为方式与您期望的不同。当你POST到me/player/next
时,端点立即响应代码204表示它收到了你的请求。
的确,这就是 Spotify API docs 所说的:
A completed request will return a 204 NO CONTENT response code, and then issue the command to the player.
这意味着您的代码看到 204 并立即继续为当前曲目调用 Spotify API。这发生在之前 Spotify 的播放器调用了上述传递的command to the player
。
我对 Spotify API 不是很熟悉,我看到这是 Beta 版 - 也许他们会在不久的将来提供更优雅的解决方案。在那之前,您最好的选择可能是重试第二次调用(有超时限制)几次,直到您确认曲目确实已更改。
这是一个简单的示例,您可以如何实现它:
updateCurrentlyPlaying(priorSongId) {
const {deviceId, token} = this.state;
let selectedSong;
let numTries = 0;
const retryFetchUntilUpdate = () => {
fetch(`https://api.spotify.com/v1/me/player/currently-playing?device_id=${deviceId}`, {
method: 'GET',
headers: {'Authorization': 'Bearer ' + token},
})
.then(response => response.json())
.then(data => {
if (data.item.id === priorSongId && numTries < 5) {
numTries += 1;
setTimeout(retryFetchUntilUpdate, 250)
} else {
selectedSong = {
name: data.item.name,
duration: Math.round(data.item.duration_ms / 1000),
artists: data.item.artists,
album: data.item.album.name,
image: data.item.album.images[0],
id: data.item.id,
uri: data.item.uri,
offset: data.offset
}
this.setState({selectedSong})
}
})
}
retryFetchUntilUpdate();
}
我在链接这两个 API 调用时遇到问题。所以基本上我正在尝试重新创建 Spotify 界面并且单独地,这些调用确实有效,这太棒了!
我还有一个 'onPlayClick' 函数,它与 'onNextClick' 的功能基本相同,如下所示,但具有不同的端点,并且是 PUT 方法而不是 POST 方法。正确播放和设置 selectedSong 的状态。
但是,调用 updateCurrentlyPlaying 的 onNextClick 没有按预期工作。预期的功能是当用户单击下一首时,歌曲将转到下一首曲目(有效!),然后更新 UI.
上的曲目信息但最终发生的是它首先更新曲目信息然后切换曲目,所以在 UI 上它在某种意义上总是 "one track behind" 我不知道为什么第二个 API 领先于第一个! :S 非常感谢任何帮助!
onNextClick = () => {
const { deviceId, token } = this.state
fetch(`https://api.spotify.com/v1/me/player/next?device_id=${deviceId}`, {
method: 'POST',
headers: { 'Authorization': 'Bearer ' + token },
})
.then(response => response.json())
.then(this.updateCurrentlyPlaying())
}
updateCurrentlyPlaying(){
const { deviceId, token } = this.state;
let selectedSong;
fetch(`https://api.spotify.com/v1/me/player/currently-playing?device_id=${deviceId}`, {
method: 'GET',
headers: { 'Authorization': 'Bearer ' + token },
})
.then(response => response.json())
.then(data => {
selectedSong = {
name: data.item.name,
duration: Math.round(data.item.duration_ms / 1000),
artists: data.item.artists,
album: data.item.album.name,
image: data.item.album.images[0],
id: data.item.id,
uri: data.item.uri,
offset: data.offset
}
this.setState({ selectedSong })
})
}
更新答案
如下所述,下面的原始答案可能仍然相关。然而,第一个问题是 this.updateCurrentlyPlaying
的调用方式。在编写 .then(this.updateCurrentlyPlaying())
时,您会立即调用 this.updateCurrentlyPlaying
,这会将 undefined
传回 Promise 链。
相反,你想要这样的东西:
onNextClick = () => {
const { deviceId, token } = this.state
fetch(`https://api.spotify.com/v1/me/player/next?device_id=${deviceId}`, {
method: 'POST',
headers: { 'Authorization': 'Bearer ' + token },
})
.then(() => this.updateCurrentlyPlaying())
}
原答案
我的猜测是您的代码没有问题,但 Spotify 的行为方式与您期望的不同。当你POST到me/player/next
时,端点立即响应代码204表示它收到了你的请求。
的确,这就是 Spotify API docs 所说的:
A completed request will return a 204 NO CONTENT response code, and then issue the command to the player.
这意味着您的代码看到 204 并立即继续为当前曲目调用 Spotify API。这发生在之前 Spotify 的播放器调用了上述传递的command to the player
。
我对 Spotify API 不是很熟悉,我看到这是 Beta 版 - 也许他们会在不久的将来提供更优雅的解决方案。在那之前,您最好的选择可能是重试第二次调用(有超时限制)几次,直到您确认曲目确实已更改。
这是一个简单的示例,您可以如何实现它:
updateCurrentlyPlaying(priorSongId) {
const {deviceId, token} = this.state;
let selectedSong;
let numTries = 0;
const retryFetchUntilUpdate = () => {
fetch(`https://api.spotify.com/v1/me/player/currently-playing?device_id=${deviceId}`, {
method: 'GET',
headers: {'Authorization': 'Bearer ' + token},
})
.then(response => response.json())
.then(data => {
if (data.item.id === priorSongId && numTries < 5) {
numTries += 1;
setTimeout(retryFetchUntilUpdate, 250)
} else {
selectedSong = {
name: data.item.name,
duration: Math.round(data.item.duration_ms / 1000),
artists: data.item.artists,
album: data.item.album.name,
image: data.item.album.images[0],
id: data.item.id,
uri: data.item.uri,
offset: data.offset
}
this.setState({selectedSong})
}
})
}
retryFetchUntilUpdate();
}