javascript - 在 Promise 中解决 Promise
问题描述
我遇到了一个问题,我有一个 react-native 应用程序,我有一组动作来显示视频(我之前记录了这些动作)。
我对所有动作都有一个 for 循环,需要等待视频达到某个时间戳才能触发动作。为此,我使用一个开关来识别我的所有操作,并在内部等待一个承诺,以便在良好的时间戳触发操作。
这是我的代码:
isTimestampReached = (timestampToWait) => {
console.log(
`timestampToWait: ', ${timestampToWait}, currentTime: ${this.videoPlayerRef.controlButtonRef.getCurrentTime()}`,
);
return new Promise((resolve, reject) => {
if (
timestampToWait <
this.videoPlayerRef.controlButtonRef.getCurrentTime() + 0.05 &&
timestampToWait >
this.videoPlayerRef.controlButtonRef.getCurrentTime() - 0.05
) {
console.log('timestamp Reached !');
resolve(true);
} else {
setTimeout(this.isTimestampReached, 100, timestampToWait);
}
});
};
previewRecording = async () => {
this.resetPlayer();
const {recordedActions} = this.state;
console.log('recordedActions: ', recordedActions);
for (const action of recordedActions) {
console.log('action', action);
switch (action.type) {
case 'play':
console.log('launch play');
// if (await this.isTimestampReached(action.timestamp)) { // this is the same as the line under
await this.isTimestampReached(action.timestamp).then(() => {
this.videoPlayerRef.setState({
paused: false,
});
console.log('setPlay');
});
break;
case 'pause':
console.log('launch pause');
await this.isTimestampReached(action.timestamp).then(() => {
console.log('set Pause');
this.videoPlayerRef.setState({
paused: true,
});
}),
console.log('pause outside loop');
break;
case 'changePlayRate':
console.log('changePlayRate');
this.videoPlayerRef.setState({
playRate: action.playRate,
});
break;
default:
console.log(`case ${action.type} not handled`);
}
}
};
我们可以看到我留在里面for loop
,switch
因为我没有得到console.log('pause outside loop');
。但正如你所看到的,我也不明白console.log('set Pause');
。所以这意味着我的 Promise 没有解决。
我认为问题在于在承诺中启动承诺,因为对于第一种情况(播放),它直接起作用。但我不知道如何解决这个问题。
预先感谢社区
PS:我只放了 javascript 标签,因为我认为这与 react 或 react-native 无关。
解决方案
这意味着我的 Promise 没有解决。我认为问题在于在承诺中启动承诺。
的确。在 的 executor 回调中new Promise
,您只调用setTimeout
但从不调用resolve()
or reject()
。100 毫秒后的isTimestampReached
调用确实创建并返回了它自己的承诺,原始的“外部”承诺永远不会被解决。你可以通过这样做来解决这个问题
setTimeout(() => {
resolve(this.isTimestampReached(timestampToWait);
}, 100);
但是使用async
/await
进行轮询要容易得多:
async isTimestampReached(timestampToWait) {
while (true) {
const currentTime = this.videoPlayerRef.controlButtonRef.getCurrentTime();
console.log(`timestampToWait: ${timestampToWait}, currentTime: ${currentTime}`);
if (timestampToWait < currentTime + 0.05 &&
timestampToWait > currentTime - 0.05) {
console.log('timestamp Reached !');
return true;
}
await new Promise(resolve => {
setTimeout(resolve, 100);
});
}
}
(你可以重构它以使用更好的循环条件,但你明白了)。
推荐阅读
- unit-testing - 质疑 TDD 中的逆变换
- android - 如何从 Android Studio 在 Windows 10 上运行 Build runner
- c# - 如何在 Dotnet core 3.1 Web 应用程序中上传文件
- typo3 - TYPO3 v9 routeEnhancers 用于多个对象
- javascript - 将对象数组的第一个属性值绑定到 chart.js
- android - 更改包名称不会更改生成的文件
- javascript - 传递给 page.evaluate 的变量未定义
- c++ - 使用 C++ 对象作为参数从 QML/JS 调用 C++ 函数
- grails - Grails 中的 JSON 视图
- python - 附加两个数据帧,带有一些重复的 datetime.date 索引,选择一个数据帧而不是另一个数据帧,使用矢量化