#javascript #reactjs #asynchronous #redux #axios
#javascript #reactjs #асинхронный #redux #axios
Вопрос:
Я выполнил действие redux для воспроизведения песни с использованием API проигрывателя Spotify. Я хочу приостановить песню через определенное время, и поэтому я устанавливаю тайм-аут внутри асинхронной функции для вызова другой асинхронной функции после истечения тайм-аута. Однако каждый раз, когда я вызываю первую функцию воспроизведения, время ожидания для второй асинхронной функции, по-видимому, увеличивается без видимой причины. Мой код:
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 amp;amp; state.spotifyPlayer.controlledPlay amp;amp; 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));
}
}
}
Ответ №1:
Опубликуйте это, если кто-то столкнется с подобной проблемой. В основном это способ, которым Javascript работает с основным потоком, поскольку js является однопоточным языком, set timeout запускает только функцию, помещенную в него, самое раннее после предусмотренной задержки. Это ненадежно, когда речь идет о коде, который должен выполняться именно в это время.
Чтобы обойти это, вы можете использовать веб-работников, которые работают как бы вне основного потока. Я случайно нашел полезный пакет npm, который уже делает это, поэтому я свяжу его: