在研究express多线程时,考虑到node的特性:异步,这样一些多线程的问题可以让异步的处理方式完成。

***按照网上说法:异步的范围更广, 多线程是实现异步的一种方式。

node的语法天生带有异步特性,但是由于作者本人之前的开发经验只是调用别人的异步函数,从来没有自己手动实现异步函数。

所以这里简单研究异步函数的实现方式(基于js的)。


异步函数的定义:     

function foo(callback) {     你自己的代码;
asyncFn(function() {
          var result = 你自己的代码;
          callback(result);
     });
}


说明:asyncFn为一个异步函数,在实现自己代码并完成计算之后,通过foo函数的回调函数callback函数将计算结果result返回。

js中常用的异步函数:setTimeout,setImmediate,process.nextTick 

在模拟测试异步操作是,经常会用setTimeout,例如:  

function foo(callback) {
     你自己的代码;
     setTimeout(function() {
          var result = 你自己的代码;
          callback(result);
     }, 1000);  //这表示异步等待时间,毫秒。
}

一般在不了解情况是通过建议使用setImmediate。其他两个异步函数的如下例:


function foo(callback) {
     你自己的代码;
     setImmediate(function() {
          var result = 你自己的代码;
          callback(result);
     });
}
 
function foo(callback) {
     你自己的代码;
     process.nextTick(function() {
          var result = 你自己的代码;
          callback(result);
     });
}

在异步回调中最常见的就是直接写匿名回调函数,如文章还是介绍的基本定义方式,就是匿名回调函数的写法。

注意:在异步函数中是不能用return 来进行返回的,如果确实要用,请确认返回值是设计的目标值(很可能在返回时,返回值还在异步函数的计算中)。

异步嵌套:

在同步代码中,如果有三个函数顺序执行,前一个的输出作为后一个的输入,只要按顺序执行三个函数即可。但在异步代码中,要做到这个就有点麻烦了。具体的原因就是因为不能像同步函数一样用return来返回值,而必须用回掉函数。所以,第二个函数要在第一个函数的回调中调用,同样第三个函数要在第二个函数的回调中调用,这就是所谓的回调嵌套。下面的例子是要先从a.txt读取其内容,然后从b.txt读取其内容,最后把两个内容合并写入ab.txt,完了后控制台打印:read and write done!


var fs = require('fs');
fs.readFile('./a.txt', function(err1, data1) {
     fs.readFile('./b.txt', function(err2, data2) {
          fs.writeFile('./ab.txt', data1 + data2, function(err) {
               console.log('read and write done!');
          });
     });
});

三个异步函数嵌套看起来挺简单的。如果有5个,10个甚至更多的异步函数要顺序执行,那要嵌套多少层呢?(大家都不喜欢身材横着长吧哈哈)说实话相当恐怖,代码会变得异常难读,难调试,难维护。这就是所谓的回调地狱或者callback hell。正是为了解决这个问题,才有了后面两节要讲的内容,用promise或generator进行异步流程管理。异步流程管理说白了就是为了解决回调地狱的问题。所以说任何事情都有两面性,异步编程有它独特的优势,却也同时遇到了同步编程根本不会有的代码组织难题。