JS 如何实现无限次数的顺序请求?

2017-08-28 10:41:38 +08:00
 abcbuzhiming
有个功能叫长轮询,很多时候用于要求不特别高的 web 消息推送或者 webim 聊天。基本原理是客户端向服务器发起一次请求后,该请求就被服务器 hold 住 n 秒(从 30-90s 不等),此时如果服务器发现有属于这个连接的新消息,就返回消息,然后本次请求结束,客户端再次发起下一次请求,无限循环。

这里面有两个难点:
请求是顺序的,一个请求结束后才发起另外一个,也就是说是链式请求,而大部分的客户端异步请求是不会等待一个完结才开始另外一个的。
请求的数目是无限的,不是有限的。类似 Porimse 这样的链式请求的实现从方式上看其实是先把有限个请求任务全部串起来,然后再让它们执行。而我这里,请求数目理论上是无限的,所以不能预先串好

有个叫 sockjs 的库在低版本 IE 上就能实现这样“无限链式请求”功能,我看了很久代码,还是没搞懂原理,请指点
4379 次点击
所在节点    JavaScript
29 条回复
Immortal
2017-08-28 15:17:46 +08:00
@t123yh socketio 对于低版本的浏览器 因该也是走的轮询
t123yh
2017-08-28 15:24:31 +08:00
@Immortal 这样也很好啊,用轮子
fulvaz
2017-08-28 16:30:31 +08:00
@iskyzh 我记得 v8 可以尾递归了, 只要写的时候注意, 不会有溢出的问题
xieranmaya
2017-08-28 17:30:37 +08:00
异步递归啊:
```js
(function r() {
fetch(url).then(r)
}())
```
lamada
2017-08-28 23:19:35 +08:00
eventstream
ryd994
2017-08-29 08:07:21 +08:00
@abcbuzhiming 有尾递归优化的情况下,递归等效于循环
这也是为什么对函数式语言尾递归优化这么重要的原因:因为函数式语言的循环一般就是递归实现的
abcbuzhiming
2017-08-29 09:25:48 +08:00
@ryd994 想请教一个问题,递归不都应该有出口吗?如果是无限循环比如 while(true),也能用尾递归等效?这什么原理
ryd994
2017-08-29 11:16:44 +08:00
@abcbuzhiming 没有尾递归优化的话,调用栈会一直往上堆,直到爆掉。所以在大多数过程式语言里,一般不建议递归太多层,而且会很小心返回条件。
有尾递归优化的话,尾调用只是等于赋值然后跳转被调用函数,不需要保留调用函数的内容。正确使用的话不会爆栈。
函数式编程只考虑基本元素,不考虑运行环境的高阶函数的话,循环只能用递归表示。
xieranmaya
2017-08-29 19:52:47 +08:00
再贴一个写法:
(async function r() {
await fetch(url)
r()
}())

楼主你要知道,异步递归不是真的递归,是不会产生调用栈的
所以对于异步代码分析什么尾递归,调用栈都基本没什么意义

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://tanronggui.xyz/t/386282

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX