NodeJS实现同步的方法


Posted in NodeJs onMarch 02, 2019

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
......

我们可以看到,所有的时间间隔都是不一样的。时间的偏移不仅包含了间隔的1s,还包含了console.log()的耗时,以及new Date()的耗时。在大量的数据统计下,时间间隔近似于1s。

问题来了,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' ]

上面的基本async模块的实现的如果了解更多关于async模块的使用,可以查询官方文档

其实nodeJS基本api也提供了异步实现同步的方式。基于Promise+then的实现

sleep = function (time) {
  return new Promise(function () {
    setTimeout(function () {
      console.log("end!");
    }, time);
  });
};
console.log(sleep(3000));

输出结果为:

Promise { <pending> }
end!

可以看出来,这里返回了Promise对象,直接输出Promise对象的时候,会输出该对象的状态,只有三种:PENDING、FULFILLED、REJECTED。字面意思很好理解。也就是说Promise有可能能实现我们异步任务同步执行的功能。我们先用Promise+then结合起来实现异步任务同步操作。

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!

在new Promise任务执行完后,调用了resolve才会执行所有的then函数,并且这些then函数是异步执行的。由输出结果可以知道。(如果所有then是顺序执行的应该是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

由于这里时间输出比较尴尬,只能通过我们来感知,本人通过个人“感知”知道了在display b过度到display a的时候大概用了3s,再过度到display c的时候大概用了5s

这里需要声明的是:才开始正式的学习nodeJS。在学习的过程中,做的笔记,很多概念与理解可能会错误,如果错误,欢迎纠正。

总结

以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,谢谢大家对三水点靠木的支持。如果你想了解更多相关内容请查看下面相关链接

NodeJs 相关文章推荐
将nodejs打包工具整合到鼠标右键的方法
May 11 NodeJs
nodejs获取本机内网和外网ip地址的实现代码
Jun 01 NodeJs
nodejs npm包管理的配置方法及常用命令介绍
Jun 05 NodeJs
Nodejs sublime text 3安装与配置
Jun 19 NodeJs
如何正确使用Nodejs 的 c++ module 链接到 OpenSSL
Aug 03 NodeJs
nodejs命令行参数处理模块commander使用实例
Sep 17 NodeJs
Nodejs下用submit提交表单提示cannot post错误的解决方法
Nov 21 NodeJs
实例分析nodejs模块xml2js解析xml过程中遇到的坑
Mar 18 NodeJs
Nodejs中Express 常用中间件 body-parser 实现解析
May 22 NodeJs
nodejs初始化init的示例代码
Oct 10 NodeJs
nodejs对mongodb数据库的增加修删该查实例代码
Jan 05 NodeJs
使用nodejs实现JSON文件自动转Excel的工具(推荐)
Jun 24 NodeJs
PHPStorm中如何对nodejs项目进行单元测试详解
Feb 28 #NodeJs
Nodejs对postgresql基本操作的封装方法
Feb 20 #NodeJs
深入理解nodejs搭建静态服务器(实现命令行)
Feb 05 #NodeJs
Nodejs实现的操作MongoDB数据库功能完整示例
Feb 02 #NodeJs
基于Koa(nodejs框架)对json文件进行增删改查的示例代码
Feb 02 #NodeJs
用Electron写个带界面的nodejs爬虫的实现方法
Jan 29 #NodeJs
NVM安装nodejs的方法实用步骤
Jan 16 #NodeJs
You might like
实用函数10
2007/11/08 PHP
PHP setcookie指定domain参数后,在IE下设置cookie失效的解决方法
2011/09/09 PHP
怎样搭建PHP开发环境
2015/07/28 PHP
PHP 根据key 给二维数组分组
2016/12/09 PHP
php实现的二叉树遍历算法示例
2017/06/15 PHP
兼容ie和firefox js关闭代码
2008/12/11 Javascript
JQuery之拖拽插件实现代码
2011/04/14 Javascript
JS访问SWF的函数用法实例
2015/07/01 Javascript
js实现不提交表单获取单选按钮值的方法
2015/08/21 Javascript
js实现的黑背景灰色二级导航菜单效果代码
2015/08/24 Javascript
浅析jquery数组删除指定元素的方法:grep()
2016/05/19 Javascript
js 动态生成json对象、时时更新json对象的方法
2016/12/02 Javascript
使用jQuery卸载全部事件的思路详解
2017/04/03 jQuery
node koa2实现上传图片并且同步上传到七牛云存储
2017/07/31 Javascript
vue如何使用 Slot 分发内容实例详解
2017/09/05 Javascript
jQuery使用bind函数实现绑定多个事件的方法
2017/10/11 jQuery
vue 虚拟dom的patch源码分析
2018/03/01 Javascript
React key值的作用和使用详解
2018/08/23 Javascript
小程序登录/注册页面设计的实现代码
2019/05/24 Javascript
Vue中跨域及打包部署到nginx跨域设置方法
2019/08/26 Javascript
vue动态循环出的多个select出现过的变为disabled(实例代码)
2019/11/10 Javascript
如何使用JS console.log()技巧提高工作效率
2020/10/14 Javascript
[01:05:32]DOTA2上海特级锦标赛主赛事日 - 3 败者组第三轮#1COL VS Alliance第一局
2016/03/04 DOTA
python类定义的讲解
2013/11/01 Python
在dataframe两列日期相减并且得到具体的月数实例
2018/07/03 Python
python获取txt文件词向量过程详解
2019/07/05 Python
使用Keras实现简单线性回归模型操作
2020/06/12 Python
一篇文章搞懂python的转义字符及用法
2020/09/03 Python
Python Pillow(PIL)库的用法详解
2020/09/19 Python
python中time包实例详解
2021/02/02 Python
信息专业毕业生五年职业规划参考
2014/02/06 职场文书
民主评议政风行风整改方案
2014/09/17 职场文书
初中成绩单评语
2014/12/29 职场文书
Java获取e.printStackTrace()打印的信息方式
2021/08/07 Java/Android
解决Mysql中的innoDB幻读问题
2022/04/29 MySQL
mysql数据库隔离级别详解
2022/06/16 MySQL