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实现的一个简单udp广播服务器、客户端
Sep 25 NodeJs
Nodejs极简入门教程(三):进程
Oct 27 NodeJs
NodeJS与HTML5相结合实现拖拽多个文件上传到服务器的实现方法
Jul 26 NodeJs
NodeJS远程代码执行
Aug 28 NodeJs
Nodejs进阶:核心模块net入门学习与实例讲解
Nov 21 NodeJs
nodejs学习笔记之路由
Mar 27 NodeJs
mac下的nodejs环境安装的步骤
May 24 NodeJs
NodeJS 实现手机短信验证模块阿里大于功能
Jun 19 NodeJs
nodejs项目windows下开机自启动的方法
Nov 22 NodeJs
详解Nodejs内存治理
May 13 NodeJs
Nodejs实现多文件夹文件同步
Oct 17 NodeJs
nodejs检测因特网是否断开的解决方案
Apr 17 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
php4的session功能评述(二)
2006/10/09 PHP
php求正负数数组中连续元素最大值示例
2014/04/11 PHP
Laravel框架实现多个视图共享相同数据的方法详解
2019/07/09 PHP
js获取单元格自定义属性值的代码(IE/Firefox)
2010/04/05 Javascript
javascript学习笔记(七)利用javascript来创建和存储cookie
2011/04/08 Javascript
改变隐藏的input中value值的方法
2014/03/19 Javascript
javascript 操作符(~、&amp;、|、^、)使用案例
2014/12/31 Javascript
JavaScript 七大技巧(一)
2015/12/13 Javascript
JS控制按钮10秒钟后可用的方法
2015/12/22 Javascript
jQuery+ajax实现滚动到页面底部自动加载图文列表效果(类似图片懒加载)
2016/06/07 Javascript
javascript中对象的定义、使用以及对象和原型链操作小结
2016/12/14 Javascript
JS中parseInt()和map()用法分析
2016/12/16 Javascript
vue.js 初体验之Chrome 插件开发实录
2017/05/13 Javascript
js 计数排序的实现示例(升级版)
2020/01/12 Javascript
Vue使用vue-draggable 插件在不同列表之间拖拽功能
2020/03/12 Javascript
[06:38]DOTA2怒掀电竞风暴 2013Chinajoy
2013/07/27 DOTA
Python利用Beautiful Soup模块搜索内容详解
2017/03/29 Python
python中文乱码不着急,先看懂字节和字符
2017/12/20 Python
Python使用matplotlib绘制多个图形单独显示的方法示例
2018/03/14 Python
python组合无重复三位数的实例
2018/11/13 Python
python将list转为matrix的方法
2018/12/12 Python
python GUI库图形界面开发之PyQt5信号与槽的高级使用技巧(自定义信号与槽)详解与实例
2020/03/06 Python
基于Python词云分析政府工作报告关键词
2020/06/02 Python
selenium+超级鹰实现模拟登录12306
2021/01/24 Python
AHAVA美国官方网站:死海海泥护肤品牌
2016/10/18 全球购物
Seavenger官网:潜水服、浮潜、靴子和袜子
2020/03/05 全球购物
C语言笔试题回忆
2015/04/02 面试题
生产副总岗位职责
2013/11/28 职场文书
个人简历中自我评价
2014/02/11 职场文书
ktv筹备计划书
2014/05/03 职场文书
项目建议书范文
2014/05/12 职场文书
社区娱乐活动方案
2014/08/21 职场文书
酒店员工辞职信范文
2015/02/28 职场文书
高考1977观后感
2015/06/04 职场文书
利用 JavaScript 构建命令行应用
2021/11/17 Javascript
JS函数式编程实现XDM一
2022/06/16 Javascript