首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
社区首页 >问答首页 >承诺resolve()被调用,但直到循环被从终止调用时才进行解析

承诺resolve()被调用,但直到循环被从终止调用时才进行解析
EN

Stack Overflow用户
提问于 2021-12-21 14:37:10
回答 2查看 327关注 0票数 0

我正在用nodejs编写一个基于游戏循环的应用程序。循环的每一次迭代都会触发一个事件发射器,并调用如下所示的更新方法:

代码语言:javascript
运行
AI代码解释
复制
  updateLoop() {
    while (!this.windowShouldClose()) {
      this.onUpdate.emit();
      this.update();
    }
  }

事件发射器似乎可以帮助在不同操作之间等待帧的游戏对象上编写异步函数,就像协同线一样。我编写了一个实用程序函数,该函数将调用事件发射器的下一个发射点,或解决该事件发射器的下一个发出时的承诺:

代码语言:javascript
运行
AI代码解释
复制
nextFrame() {
  return new Promise((resolve) => {
    this.onUpdate.once(resolve); // event emitter will resolve promise on next emit()
  })
}

nextFrameCallback(callback) {
  this.onUpdate.once(callback);
}

// example use
async doThingsAsync() {
  // do something
  await this.nextFrame();
  // do something else on the next frame / loop iteration
}

虽然基于回调的函数按预期工作,但承诺版本的nextFrame()在我所期望的时候并不能解决这个问题。在我的示例中,await nextFrame()只在updateLoop()的外部循环退出后才进行解析。我调整了一个console.log来承诺查找更多的内容,并发现控制台日志和解析()确实在循环中被调用,但是等待它仍然会等待循环完全终止。

代码语言:javascript
运行
AI代码解释
复制
nextFrameDebug() {
  return new Promise((resolve) => {
    this.onUpdate.once(() => {
      console.log('debug nextFrame'); // this prints during the expected loop iteration
      resolve(); // this does not actually resolve until updateLoop() terminates
    })
  })
}

这里有一个JSFiddle演示了上面的函数:https://jsfiddle.net/8L4wub29/5/ --似乎我已经接近了一个功能解决方案,但是我对承诺或异步函数有一些误解。这与从循环中调用异步函数有关吗?我如何编写nextFrame()以使承诺在循环的下一次迭代中得到解决,而不是在循环退出之后?我意识到,对于游戏中的大多数功能,毫秒的超时更有用,但在某些情况下,比如等待物理更新,游戏可能希望只等待一个帧作为实用函数。基于回调的版本工作正常,但是如果您需要多次使用它,则需要嵌套它,这看起来不像使用await那么干净。

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2021-12-21 15:17:29

承诺提供的保证是,它们的.then回调将始终被异步调用。这意味着,如果你有一些随机的承诺,你会做这样的事情:

代码语言:javascript
运行
AI代码解释
复制
somePromise.then(() => {
  console.log('inside');
});
console.log('outside');

您将始终看到“外部”和“内部”,即使承诺已经处于已解决的状态。承诺是这样设计的,因此您可以确定执行的顺序,因此不必修复涉及这两个订单的痛苦错误。当您使用await而不是显式.then的时候,情况也是一样:await之后的代码必须等待承诺解决,并且调用堆栈返回到系统代码。

因此,当您从回调切换到承诺时,您从可以在循环中间同步调用回调的代码转变为必须等待执行才能返回的代码。只有在updateLoop返回或生成之后,代码才能在承诺之后运行。因为这个循环直到结束才会返回或屈服,所以所有的承诺都会被推迟到循环之后。

如果您需要updateLoop同步运行,则不能使用此承诺。如果updateLoop应该是异步的(可能在运行下一步之前设置超时),那么可以使用承诺,但是我需要更多的细节来说明您试图做什么来给出一个示例。

票数 1
EN

Stack Overflow用户

发布于 2021-12-21 17:27:01

回答我自己的问题,因为我找到了提供预期功能的东西。我只是简单地更新了示例中的updateLoop()调用。

代码语言:javascript
运行
AI代码解释
复制
  async updateLoop() {
    while (!this.windowShouldClose()) {
      await null;
      this.onUpdate.emit();
      this.update();
    }
  }

有人能在更明确的情况下发表评论吗?为什么现在会产生预期的效果?除非我添加了一个等待语句,否则将函数更改为异步不会影响承诺的解析点。我的假设是,包括一个等待语句,释放事件循环,这最终允许承诺解决。如果使用此函数编辑上述JSfiddle,则控制台中打印的数字将与打印语句"expect“不一致--这仅与计数器增加有关。执行命令似乎是正确的。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/70442303

复制
相关文章
OpenStack命令创建一个指定的卷
查看卷类型列表 [root@controller ~]# openstack volume type list ID Name Is Public 0fed6ef3-4b9b-4519-bdb0-36fecb7c5b94 hdd True 05c4ce95-8e73-4ccf-8025-304b738d1098 ssd True 创建一个卷名叫 wocaoa的卷 大小为:100G 类型为:SSD [root@controller ~]# openstack volume create wocaoa --
院长技术
2020/06/13
1.1K0
在数组内删除指定元素_数组对象删除某一个指定对象
一般来说,我们用数组这种数据结构最多的情况,是用来做查询,时间复杂度为O(1),那么在这里我们来看一下如何用在数组中插入元素和删除元素。 数组的适用场景: 一般在查询中,适用数组的情况是比较多,因为可以根据下标直接访问元素,时间复杂度是O(1),所以适用于读多写少的场景。 数组的插入和删除元素,一般时间复杂度都是O(N),比较麻烦,所以对于插入和删除操作中,不建议选用数组这种数据结构,可以考虑链表。
全栈程序员站长
2022/09/22
2.2K0
近2万字详解JAVA NIO2文件操作,过瘾!
从classpath中读取过文件的人,都知道需要写一些读取流的方法,很是繁琐。最近使用IDEA在打出.这个符号的时候,一行代码让人激动不已:竟然提供直接读出bytes字节的方法。
xjjdog
2020/03/17
8920
让一个 csproj 项目指定多个开发框架
发布于 2018-01-21 03:28 更新于 2018-08-31 09:56
walterlv
2018/09/18
1K0
让一个 csproj 项目指定多个开发框架
FFmpeg如何将一个gif嵌入视频指定位置并指定显示时间
ffmpeg version 2022-04-07-git-607ecc27ed-full_build-www.gyan.dev Copyright (c) 2000-2022 the FFmpeg developers
乔达摩@嘿
2023/09/21
3250
Java从一个数组指定位置拷贝到另外一个数组的指定位置-新法
根据提示我们发现可以通过 System.arraycopy() 方法来替换这个for循环。
明明如月学长
2021/08/27
7000
如何使用git clone一个指定文件或者目录
1.先创建一个空目录 mkdir -p /use/dir 2.进入创建的目录 cd /use/dir 3. 执行git init 初始化git git init 4. 和远程git 库进行关联 git remote add -f origin git@git.xxx.com:xxx/xxx.git 5. 开启稀疏检出 git config core.sparsecheckout true 6. sparse-checkout文件里写入要拉取的文件或者文件夹 echo "clone_file" >> .gi
特特
2022/05/22
11.8K0
Python 以一个指定的间隔定时循环执
http://www.linuxidc.com/Linux/2014-03/97555.htm
py3study
2020/01/06
1.3K0
一个文本按指定字符分割成多个文本
今天师兄扔给我一个txt,说:“来,小郭,你把这个文本处理一下,按照指定字符分割成多个文本。”这下可难倒我了,不过好在功夫不负有心人,几经周折之后把它完成了。
快学Python
2021/08/09
3.8K0
js去除字符串最后一个指定字符
具体实现代码如下: function delLast(str, target) { return str.split('').reverse().join('').replace(target, '').split('').reverse().join(''); } const str = delLast('asdfghhj', 'h') console.log(str) // asdfghj
IT工作者
2021/12/28
2.9K0
生成一个指定长度的随机数
生成随机数在日常工作中的使用率也很高。虽说Python标库自带了生成随机数的功能。但是我想写一个函数,既可以生成数字,又可以生成字符串。而且还可以指定长度,自由自在的生成需要的数据。把它放在我的工具库中,工作过程中需要的时候,随时随地调用,可不快哉。
TalkPython
2020/05/27
1.5K0
Unreal随笔系列4:UE4关闭指定平台距离场烘培
我们项目构建了Linux版本的客户端,用于DS的压测。最近一段时间, Unreal Linux Client的构建时间异常的久,所以简单的探究了下Cook的原理。最终通过关闭linux平台下的距离场(Distance Field)烘培,缓解了构建时间的问题。
JohnYao
2023/03/23
5750
Unreal随笔系列4:UE4关闭指定平台距离场烘培
Dispatch – 让指定程序使用指定网卡
在参与迅雷水晶项目之后,reizhi 开始想尽一切办法提高挖矿的速度。由于每一个水晶资格账号允许同时在路由器以及 PC 上运行,同时挂机无疑能够大大增加水晶产出速度。但迅雷水晶运行时会产生大量 TCP/UDP 连接,严重影响无线网卡吞吐量,导致挖水晶时上网速度缓慢。由于有线连接并不可行,最终决定使用双无线连接,一个用于上网,另一个专职挖水晶。但问题也随之而来,无论是 Windows 还是迅雷水晶都没有提供指定网卡的功能,同时连接两个无线后并没有获得想要的效果。于是在 Google 上搜索“指定程序 网卡”,但最终一无所获。最后想起很久以前用过 Connectify 所附带的 Dispatch 似乎提供这个功能,遂下载试用。
reizhi
2022/09/26
4.7K0
Dispatch – 让指定程序使用指定网卡
视频融合平台EasyCVR如何下载指定时间段的录像文件?
EasyCVR视频融合平台部署轻快、功能灵活,在视频能力上,可提供视频直播、录像、回放、检索、云存储、告警上报、集群以及平台级联等功能。平台可支持多协议、多类型设备接入,包括国标GB28181、RTMP、RTSP/Onvif、海康SDK、大华SDK、Ehome等,对外可分发RTSP、RTMP、FLV、HLS、WebRTC等格式的视频流。
TSINGSEE青犀视频
2022/09/13
4310
Java 如何返回一个指定范围的随机数
使用 RandomUtils 类中定义的方法,RandomUtils 定义在下面的 Package 中
HoneyMoose
2019/01/22
1.7K0
【转】指定文件、指定行、指定代码块不使用 ESLint 语法检查
在使用了 eslint 进行代码检查后,可以大幅提高我们的代码规范。但是,在某些情况下,我们必须去写一些违反规则的代码。如果写了这些代码,则势必会导致各种提示报错。这种情况下,如果不去处理,则会导致项目警告越来越多,最终不知道哪些是必须的,哪些是可以修正的。 因此,在某些地方,禁用检查就变得十分重要了。随便搜索了一下,找到了这篇博文,写得还比较全面,因此转载过来了。
FungLeo
2019/07/02
1.7K0
Js 删除 指定Domin 指定 path 下的 cookie中指定的内容
假设,cookie中的key 为 keyName 则如果想删除客户端浏览器中某 Domin 某 Path 下的cookie内容的 keyName这一项,则可以操作如下(此时 Domin 为 xxx.com.cn,Path 为 /):
MickyInvQ
2020/09/27
4K0
Java NIO File操作
今天在工作中遇到一个很奇怪的问题。使用java.io.File进行文件操作抛出了FileNotFoundException,代码如下 //但事实上在`/somewhere`目录下存在文件`测试.txt` FileInputStream fin = new FileInputStream(new File("/somewhere/测试.txt")); 在网络找了下,发现一个可能是由于路径中包括非ASCII字符,详见这里 最后找到了解决方案 1 InputStream fin = Files.newInputS
jeremyxu
2018/05/10
1.4K0
点击加载更多

相似问题

setState在UI上没有正确显示更改

25

语义UI消息列表没有正确显示

11

顺风3调色板没有正确生成

18

UIImageView没有显示在UI中。

35

调色板没有返回正确的长度?

14
添加站长 进交流群

领取专属 10元无门槛券

AI混元助手 在线答疑

扫码加入开发者社群
关注 腾讯云开发者公众号

洞察 腾讯核心技术

剖析业界实践案例

扫码关注腾讯云开发者公众号
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档