NodeJS被打上了单线程、非阻塞、事件驱动…..等标签。
在单线程的情况下,是无法开启子线程的。经过了很久的研究,发现并没有thread函数!!!但是有时候,我们确实需要“多线程”处理事务。nodeJS有两个很基础的api:setTimeout和setInterval。这两个函数都能实现“异步”。
nodeJS的异步实现:nodeJS有一个任务队列,在使用setInterval函数的时候,会每隔特定的时间向该任务队列增加任务,从而实现“多任务”处理。但是,“特定的时间”不代表是具体的时间,也有可能是会大于我们设定的时间,也有可能小于。
我们跑跑下面代码块
setInterval(function() {
console.log(new Date().getTime());
}, 1000);
1490531390640
1490531391654
1490531392660
1490531393665
1490531394670
1490531395670
1490531396672
1490531397675
......
问题来了,setInterval是能实现多任务的效果,但是怎样才能实现任务之间的同步操作呢?这里实现的方法是通过回调函数实现的。
function a(callback) {
// 模拟任务a耗时
setTimeout(function() {
console.log("task a end!");
// 回调任务b
callback();
}, 3000);
};
function b() {
setTimeout(function() {
console.log("task b end!");
}, 5000);
}
a(b);
这里举了一个很简单的例子,就是将b方法的实现赋值给a方法的callback函数从而实现函数回调,但是会有个问题。假设a方法依赖于b方法,b方法依赖于c方法,c方法依赖于d方法…..也就意味着每个方法的实现都需要持有上一个方法的实例,从而实现回调。
function a(b, c, d) {
console.log("hello a");
b(c, d);
};
function b(c, d) {
console.log("hello b");
c(d);
};
function c(d) {
console.log("hello c");
d()
};
function d() {
console.log("hello d");
};
a(b, c, d);
hello a
hello b
hello c
hello d
如果有类似于sync的函数能让任务顺序执行就更好了。终于找到了async这个库
$ npm instanll async
async = require("async");
a = function (callback) {
// 延迟5s模拟耗时操作
setTimeout(function () {
console.log("hello world a");
// 回调给下一个函数
callback(null, "function a");
}, 5000);
};
b = function (callback) {
// 延迟1s模拟耗时操作
setTimeout(function () {
console.log("hello world b");
// 回调给下一个函数
callback(null, "function b");
}, 1000);
};
c = function (callback) {
console.log("hello world c");
// 回调给下一个函数
callback(null, "function c");
};
// 根据b, a, c这样的顺序执行
async.series([b, a, c], function (error, result) {
console.log(result);
});
hello world b
hello world a
hello world c
[ 'function b', 'function a', 'function c' ]
其实nodeJS基本api也提供了异步实现同步的方式。基于Promise+then的实现
sleep = function (time) {
return new Promise(function () {
setTimeout(function () {
console.log("end!");
}, time);
});
};
console.log(sleep(3000));
Promise { <pending> }
end!
sleep = function () {
return new Promise(function (resolve, reject) {
setTimeout(function () {
console.log("start!");
resolve();
}, 1000);
})
.then(function () {
setTimeout(function () {
console.log("end!");
}, 2000);
})
.then(function () {
console.log("end!!");
})
};
console.log(sleep(1000));
Promise { <pending> }
start!
end!!
end!
不过,还有更加优雅的方式:使用async+await。
display = function(time, string) {
return new Promise(function (resovle, reject) {
setTimeout(function () {
console.log(string);
resovle();
}, time)
});
};
// 执行顺序:b a c
fn = async function () {
// 会造成阻塞
await display(5000, "b");
await display(3000, "a");
await display(5000, "c");
}();
b
a
c