NodeJS如何实现同步的方法示例


Posted in NodeJs onAugust 24, 2018

前言

众所周知,异步是得天独厚的特点和优势,但同时在程序中同步的需求(比如控制程序的执行顺序为:func1 -> func2 ->func3 )也是很常见的。

下面这篇文章主要介绍了关于NodeJS实现同步的相关内容,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的前后端分离的思考与实践(五)多终端适配
Sep 26 NodeJs
轻松创建nodejs服务器(7):阻塞操作的实现
Dec 18 NodeJs
Nodejs学习item【入门手上】
May 05 NodeJs
让nodeJS支持ES6的词法----babel的安装和使用方法
Jul 31 NodeJs
用nodejs实现json和jsonp服务的方法
Aug 25 NodeJs
nodejs读取本地中文json文件出现乱码解决方法
Oct 10 NodeJs
NodeJs实现简单的爬虫功能案例分析
Dec 05 NodeJs
nodejs dgram模块广播+组播的实现示例
Nov 04 NodeJs
nodejs+koa2 实现模仿springMVC框架
Oct 21 NodeJs
nodejs中的异步编程知识点详解
Jan 17 NodeJs
使用 Koa + TS + ESLlint 搭建node服务器的过程详解
May 30 NodeJs
Nodejs中的JWT和Session的使用
Aug 21 #NodeJs
nodejs 如何手动实现服务器
Aug 20 #NodeJs
nodejs实现一个word文档解析器思路详解
Aug 14 #NodeJs
NodeJs项目中关闭ESLint的方法
Aug 09 #NodeJs
nodejs之koa2请求示例(GET,POST)
Aug 07 #NodeJs
NodeJS实现自定义流的方法
Aug 01 #NodeJs
nodejs 生成和导出 word的实例代码
Jul 31 #NodeJs
You might like
新的一年,新的期待:DC在2020年的四部动画电影
2020/01/01 欧美动漫
require(),include(),require_once()和include_once()的异同
2007/01/02 PHP
PHP编程过程中需要了解的this,self,parent的区别
2009/12/30 PHP
PHP GD库生成图像的几个函数总结
2014/11/19 PHP
10条php编程小技巧
2015/07/07 PHP
基于php实现七牛抓取远程图片
2015/12/01 PHP
php 实现301重定向跳转实例代码
2016/07/18 PHP
PHP登录(ajax提交数据和后台校验)实例分享
2016/12/29 PHP
PHP排序算法之简单选择排序(Simple Selection Sort)实例分析
2018/04/20 PHP
通过判断JavaScript的版本实现执行不同的代码
2010/05/11 Javascript
十个迅速提升JQuery性能让你的JQuery跑得更快
2012/12/10 Javascript
浅析javascript的间隔调用和延时调用
2014/11/12 Javascript
JavaScript时间转换处理函数
2015/04/14 Javascript
简单讲解AngularJS的Routing路由的定义与使用
2016/03/05 Javascript
温习Javascript基础语法之词法结构
2016/05/31 Javascript
Javascript实现汉字和拼音互转的终极方案
2016/10/19 Javascript
Angular企业级开发——MVC之控制器详解
2017/02/20 Javascript
requirejs + vue 项目搭建详解
2017/06/16 Javascript
谈谈对vue响应式数据更新的误解
2017/08/01 Javascript
webpack引入eslint配置详解
2018/01/22 Javascript
原生JS实现循环Nodelist Dom列表的4种方式示例
2018/02/11 Javascript
JS简单实现动态添加HTML标记的方法示例
2018/04/08 Javascript
基于打包工具Webpack进行项目开发实例
2018/05/29 Javascript
webpack 静态资源集中输出的方法示例
2018/11/09 Javascript
详解从NodeJS搭建中间层再谈前后端分离
2018/11/13 NodeJs
JavaScript内置对象math,global功能与用法实例分析
2019/06/10 Javascript
微信小程序实现一个简单swiper代码实例
2019/12/30 Javascript
vant 解决tab切换插件标题样式自定义的问题
2020/11/13 Javascript
python+pyqt5实现KFC点餐收银系统
2019/01/24 Python
python装饰器的特性原理详解
2019/12/25 Python
python 解决Fatal error in launcher:错误问题
2020/05/21 Python
python hmac模块验证客户端的合法性
2020/11/07 Python
使用CSS3制作响应式导航菜单的方法
2015/07/12 HTML / CSS
2014年单位工作总结范文
2014/11/27 职场文书
2014年大学学生会工作总结
2014/12/02 职场文书
基于Python实现的购物商城管理系统
2021/04/27 Python