【问题标题】:How to call an async function inside setTimeout, inside another Async function?如何在另一个异步函数中调用 setTimeout 中的异步函数?
【发布时间】:2020-11-17 21:42:30
【问题描述】:

我使用 Spotify 播放器的 API 制作了一个 redux 操作来播放一首歌曲。我想在一段时间后暂停歌曲,所以我在异步函数中设置了一个超时,以便在超时结束后调用另一个异步函数。但是,每次我调用第一个播放函数时,第二个异步函数的超时似乎都会无缘无故地增长。我的代码:

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 reactjs asynchronous redux axios


    【解决方案1】:

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

    为了解决这个问题,您可以使用在主线程之外工作的网络工作者。我碰巧找到了一个有用的 npm 包,它已经这样做了,所以我会链接它:

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

    【讨论】:

      猜你喜欢
      • 2020-09-18
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-03-09
      • 1970-01-01
      • 2021-02-21
      • 1970-01-01
      • 2021-08-07
      相关资源
      最近更新 更多