node.js 支持函数作为参数注册回调函数,彰显其支持异步处理特性

2017-12-10 16:09:27 +08:00
 Juggernaut
C 也同样支持函数可以作为参数注册回调,而且检查严格,node.js 根本不作检查,等运行就 crash·

有木有同感
4108 次点击
所在节点    Node.js
27 条回复
bramblex
2017-12-10 16:19:48 +08:00
Diss nodejs 你至少拿 c 艹 11 的 lambda 吧…
zjcqoo
2017-12-10 16:34:23 +08:00
typescript 欢迎你
Juggernaut
2017-12-10 16:34:34 +08:00
@bramblex 倒不是 diss,node.js 新手,之前只有 C 相关经验,学习的过程中有些疑惑,所以来交流交流;
node.js 标榜异步处理,我现在的理解就是注册回调,把那些耗费时间的处理扔到回调函数里面去处理,不要阻塞 node.js 处理的单线程即可,其实工作还是在那,只不过是谁(线程)来处理的问题,node.js 很取巧的把重活累活都扔给别人了…是不是可以这样理解?

多谢大侠讨论
bramblex
2017-12-10 16:43:37 +08:00
@Juggernaut

如果你只有 c 基础的话,那你首先要理解的在一门函数式语言里面,一个函数和一个 int 或者一个 string 是一样的东西,可以在运行时被创建,被传递。

函数作为参数不是什么新奇的操作,所有语言都能这么干,重点的一个函数能接受函数作为参数并且能返回一个全新的函数。

接下来再讲讲异步。

在 jsruntime 里面
snnn
2017-12-10 16:46:48 +08:00
光一个函数怎么做回调啊。还得有 context。
codehz
2017-12-10 16:47:52 +08:00
C 函数不支持闭包
ObjC 的一个扩展倒是可以支持闭包
bramblex
2017-12-10 16:48:04 +08:00
在 js runtime 里面,永远都有且只有一条线程在执行 js 代码。worker 之类的情况先不讲。

所以只要是用 js 写的代码,不管你写在哪里,只要是 js,一旦阻塞,那整个程序都会阻塞。

不会阻塞的是提供的 api 不会阻塞。
bramblex
2017-12-10 16:53:57 +08:00
@snnn c 里强行靠指针和全局变量来回调的,至少折腾 moogose 的时候着实被恶心了一次。
BOYPT
2017-12-10 17:06:10 +08:00
一般 node 里面不是为了回调而回调,而是因为涉及异步 io。
Juggernaut
2017-12-10 17:19:31 +08:00
@bramblex 感谢🙏
1、函数在运行时被创建,这个该如何理解? c 的函数调用也是运行时创建,离开后销毁;
2、js 处理由一个线程负责,js 处理阻塞了该线程也就阻塞了,这个理解,你说的 API 不阻塞是什么意思,无法体会…
再次感谢
momomirage
2017-12-10 17:24:41 +08:00
你既然学过 c, 可以对比一下: c 的函数本身都是静态分配的, 编译好即使不运行, 用 nm 也可看到.

相对地, 你可以考虑一下纯 c 怎么实现一个 Function.prototype.bind
SuperMild
2017-12-10 17:54:56 +08:00
1. 别的语言当然也会用自己的方法实现异步,只是在 Node 里写异步更轻松一些
2. 动态语言、鸭子语言当然是在运行时才“检查”的(也不是检查,就是实在运行不了 crash ),想更严格地提前检查就用别的办法(办法有很多)。这有坏处也有好处,世事没有完美。
secondwtq
2017-12-10 18:34:36 +08:00
node 这个所谓的回调学名叫 CPS

异步( asynchronous )可以简单理解为领导安排下去一个事情,然后就不用管了,等到下面干完了再通知回来
典型栗子是 OS 的中断机制,也可以说基于中断的 IO 本身就是异步的
至于处理是否“耗费时间”,还有线程什么的,站在异步的角度都属于 implementation detail,异步就是指上面那个机制

非阻塞( non-blocking )直观理解就是 POSIX API 里面的 fcntl(fd, F_SETFL, O_NONBLOCK),区别是 read 和 write 调用立即返回,但不一定成功(返回值会 indicate 这个状态),放到 node 里面就是 fs.readFile 这种在它自己的函数里面是立即返回的
这个东西玩过 nginx 之类的应该明白

这些 term 的区别是很微妙的
wwqgtxx
2017-12-10 20:06:47 +08:00
@Juggernaut 区别在于 c 的函数是在编译期间就生成的,而 js 的函数在运行时被执行到定义语句的时候才被创建,而且类似于 js/python 这类语言的函数本质上都是一个对象,所以可以在一个函数中动态创建一个新的函数作为返回值
leekafai
2017-12-10 22:55:23 +08:00
支持楼主转 java
esw
2017-12-10 23:27:32 +08:00
感觉题主没明白 node 异步的本质

js 核心主要分两部分:v8 和 libuv,v8 用来解释 js 代码本身

libuv 用来支持异步操作,例如创建定时器,发送网络请求等等

libuv 实际上是用 c 写的事件循环框架,支持 c 以回调的方式运行。所以通过 libuv 结合 v8 写出一下常用操作的 binding (定时器,网络,文件等),node 就支持了异步。

关于 libuv,可以参考 http://docs.libuv.org/en/v1.x/
cctv1005s927
2017-12-11 00:00:03 +08:00
@Juggernaut 在 NodeJS 中不阻塞的 API 通常由原生方法,或者基于原生方法构建的 API,最简单的例子就是 fs.readFile,或者是 HTTP 相关的 API,在 node 层来看是不阻塞的,通过回调函数来告知过程结束。nodejs 下面还有一个 libuv,libuv 会创建线程的,但是这一层不是由 js 来负责。
gnaggnoyil
2017-12-11 01:17:26 +08:00
对于 LZ 这种声称"只有 C 相关经验"的人来说 call/cc 真是一种降维打击.API 不同步有什么难理解的?凭什么所有语言的运行模型都必须像 C 那样只能沿着子程序调用链走.更何况 LZ 连 C 都没搞明白."函数调用运行时创建,离开后销毁".麻烦 LZ 能不能先解释解释"函数调用的创建和销毁"是怎么一回事.
Juggernaut
2017-12-11 10:36:58 +08:00
@gnaggnoyil 这个……我不是来说 nodejs 不好的,学习了 nodejs 几天,一些思路与想法与大伙交流而已;至于函数创建和销毁的问题,因为只有 C 经历,我的理解是就是函数相关堆栈的申请释放,C 中的函数是执行过程的集合;不知道你所说的 nodejs 中的函数创建 /销毁是什么概念
Juggernaut
2017-12-11 10:42:44 +08:00
@gnaggnoyil 大佬息怒,wwqgtxx 同学给我解释了 nodejs 的函数创建与释放了~

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

https://www.v2ex.com/t/413507

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

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

© 2021 V2EX