如何在setTimeout中调用异步函数,在另一个异步函数中调用



我用Spotify播放器的API做了一个redux动作来播放一首歌。我想在一定时间后暂停歌曲,所以我在异步函数中设置了一个超时,以便在超时结束后调用另一个异步函数。然而,每次我调用第一个play函数时,第二个异步函数的超时似乎都会无故增加。我的代码:

let timeoutId
...
export const playElement = (accessToken, songUri, refreshToken, start, duration, deviceId) => async (dispatch) => {
dispatch(loading());
clearTimeout(timeoutId)
timeoutId = setTimeout(async () => {
await dispatch(pausePlayer(accessToken, refreshToken, deviceId, songUri))

}, duration*1000)

try { 
const url = deviceId === '' ? '/me/player/play' : `/me/player/play?device_id=${deviceId}`;
await spotify.put(
url,
{ position_ms: start * 1000, uris: [songUri] },
{
headers: {
Authorization: `Bearer ${accessToken}`,
Accept: 'application/json',
'Content-Type': 'application/json',
},
}
);

dispatch({
type: PLAY,
playing: true,
})
} catch (error) {
dispatch(returnErrors(error));
if (error.response.status === 401) {
const newAccessToken = await dispatch(refreshAccessToken(refreshToken));
dispatch(playElement(newAccessToken, songUri, refreshToken, start, duration, deviceId));
}
if (error.response.status === 404) {
const newDeviceId = await dispatch(getDeviceId(accessToken));
dispatch(playElement(accessToken, songUri, refreshToken, start, duration, newDeviceId));
}
}

dispatch(notLoading());
};
export const pausePlayer = (accessToken, refreshToken, deviceId, songUri) =>  async (dispatch, getState) => {
try { 
let state = getState();
const url = deviceId === '' ? '/me/player/pause' : `/me/player/pause?device_id=${deviceId}`;
if (state.spotifyPlayer.playing && state.spotifyPlayer.controlledPlay && state.spotifyPlayer.song === songUri) { 
await spotify.put( 
url,
{}, {
headers: {
Authorization: `Bearer ${accessToken}`,
},
}
)
}
dispatch({
type: PAUSE,
payload: false
})
} catch (error) {
dispatch(returnErrors(error));
if (error.response.status === 401) {
const newAccessToken = await dispatch(refreshAccessToken(refreshToken));
dispatch(pausePlayer(newAccessToken, deviceId));
}
if (error.response.status === 404) {
const newDeviceId = await dispatch(getDeviceId(accessToken));
dispatch(pausePlayer(accessToken, newDeviceId));
}
}
}

如果有人遇到类似问题,请发布此消息。基本上,这就是Javascript处理主线程的方式,因为js是一种单线程语言,所以设置超时只会在提供的延迟后的最早运行其中的函数。当涉及到需要在那个时候准确执行的代码时,这是不可靠的。

为了解决这个问题,你可以使用在主线程之外工作的网络工作者。我碰巧发现了一个有用的npm包,它已经做到了这一点,所以我将把它链接起来:

https://www.npmjs.com/package/worker-timers

最新更新