产生问题的经过
手头有个项目,遇到一个问题,nodejs中通过执行shell命令来执行本地程序,我希望是先执行本地程序,得到返回结果,做出if判断。
所以我将执行本地程序的代码放在了if判断的前面,在我的印象中nodejs基于js,js是单线程,同步执行,所以这段程序一定是按顺序执行。但结果是得不到返回结果总出错。
解决问题
问题得到解决,两步:
1.查看官方文档,由于我做的是火狐扩展,我参考的是MDN官方文档
2.调试,不断地调试,动手比空想强。
这里执行本地程序时间长,nodejs这里是异步执行,所以还没得到返回结果就进行了判断。
解决的办法是把判断程序放在了child_process.exec('shell', callback)中的回调函数callback中。(其实nodejs官方文档中支持execSync直接支持同步执行,可惜火狐扩展中不支持这个方法。)
新的问题
1.nodejs执行异步的原理,js是否能执行异步,单线程如何实现异步?
2.回调函数是什么,如何利用它执行异步?
解决新的问题
1.nodejs的单线程执行实际上只是针对我们所写的js代码而言的,它的底层实际上用的是c/c++,遇到I/O这样的耗时量大的底层会开启一个线程执行一个回调函数。举个栗子。上一幅图具体来说,当我们调用 fs.open 时,Node.js 通过 process.binding 调用 C/C++ 层面的 Open 函数,然后通过它调用 Libuv 中的具体方法 uv_fs_open,最后执行的结果通过回调的方式传回,完成流程。Libuv就是用c++编写的底层。
而这种异步模式下,实现同步,就可以用以上提到的回调函数的方法来写同步。文章参考1,文章参考2.
2.js是毫无疑问的单线程,同一时间段只能完成一件事情,但这并不代表它没有办法实现异步,异步和单线程并没有直接的关系,实际上有好几种方法能够实现,可以参考文章。
3.回调函数是指是指通过函数参数传递到其它代码的,某一块可执行代码的引用。即可以简单理解为是函数被当作参数传入另外一个函数当中,并在那个函数中被调用。
从以上也可以看到,回调只是一种执行方法,既有异步回调,也有同步回调。举个简单栗子:
var b = function (){
//执行相关的代码
}
var a = function (b){
//执行相关的代码
b();
}
a(b);
这是同步回调。
如果f1是一个很耗时的任务,f2需要f1的结果执行,可以把它们写成
function f1(callback){
setTimeout(function () {
// f1的任务代码
callback();
}, 1000);
}
f1(f2);
这样js会先执行其他的主要逻辑,js线程空闲一秒之后再执行这个操作。从而实现异步。
文章参考
总结
写下这篇文章的过程其实也是我弄清楚其中原委的过程,这只是一个很细节的问题,但是思考的过程却十分漫长。共勉。