运维开发网

回调函数的详细介绍,异步和同步的基本js介绍

运维开发网 https://www.qedev.com 2022-05-24 15:39 出处:网络
Node.js是一个基于Chrome?V8引擎的JavaScript运行时。类似于Java中的JRE,.Net中的CLR。本文将详细为大家介绍Node.js中的回调函数及异步与同步,感兴趣的可以了解一

Node.js是一个基于Chrome?V8引擎的JavaScript运行时。类似于Java中的JRE,.Net中的CLR。本文将详细为大家介绍Node.js中的回调函数及异步与同步,感兴趣的可以了解一

经过前两天的学习,今天对Node.js有了初步的了解,其他内容我会继续学习,整理出来分享。如有不足之处,请指正。


回调函数


1. 什么是回调函数?

回调函数,或者简单地称为call-back [call-back]将一个A函数作为参数传递给另一个B函数。在B函数执行期间,根据定时或条件决定是否调用A函数。a函数是B函数的回调函数。


2. 回调函数实现机制

回调函数的实现机制如下:

定义一个回调函数(普通函数);将回到函数的引用地址作为参数传递给调用者;当特定的事件或条件发生时,调用者使用函数指针调用回调函数对事件进行处理。


3. 回调函数用途

JavaScript中广泛使用回调函数,最简单的场景是事件注册或异步函数。比如当用户点击一个按钮,需要做出相应的响应时,就会用到回调函数。


4. 回调函数示例

以常用的setInterval为例,即show作为参数传递给setInverval,所以show是setInterval的回调函数,如下图:

function show(){ console.log("今天星期三,又是快乐的一天"); } setInterval(show,1000);

执行结果如下:


setInterval的参数描述如下:



异步与同步


1. 什么是异步与同步?

同步:一个任务等待前一个任务完成,然后执行。程序的执行顺序与任务的排列顺序一致,是同步的。

异步:每个任务都有一个或多个回调函数。前一个任务完成后,回调函数代替后一个任务执行,后一个任务在前一个任务完成前开始执行,所以程序的执行顺序和任务的排列顺序不一致,这就是异步。


2. 同步示例

也就是说,同步是按顺序执行的,有一个顺序,如下:

console.log("1111");console.log("2222");console.time("t1");for(var i=0;ilt;1000000;i++){}console.timeEnd("t1");console.log("3333");

如下同步执行结果:



3. 异步示例一

异步由回调函数执行,如下所示:

console.log("1111");console.log("2222");setTimeout(function(){ console.time("t1"); for(var i=0;ilt;1000000;i++){ } console.timeEnd("t1");},1000);console.log("3333");

示例执行结果如下:



4. 异步示例二

即使主线程被阻塞,异步回调函数也必须等待主线程完成后才能执行。如下所示:

console.log("1111");console.log("2222");setTimeout(function(){ console.log("2222-3333");},15);console.time("t1");for(var i=0;ilt;100000000;i++){}console.timeEnd("t1");console.log("3333");

示例执行结果


关于setTimeOut和setInterval的说明如下:

setTimeOut和setInterval两个函数是同步执行,但是函数的回调函数参数是定时器异步执行。setTimeOut和setInterval两个函数的最小时间间隔为10-15ms,即使设置成0,也是如此。异步函数的执行时间,永远在同步执行完之后再执行。

主线程和任务线程的执行顺序参见下图:



异步的实现

在Node.js中,有三种方法可以实现异步:

回调函数,回调函数不一定是异步,但是异步一定有回调函数。事件【基于回调】Promise【ES6新增】


1. 回调函数的同步示例

回调函数也可以是同步的,如下所示:

console.log("1111"); var arr=[1,2,3,4]; arr.forEach(function(v,i){ console.log(v); }); console.log("2222");

示例执行结果



2. 异步事件示例

定义一个服务,并在被请求时返回相应的信息。如下所示:

var http=require("http");var server=http.createServer();server.on('request',function(req,res){ res.writeHead(200,{"Content-Type":'text/html;charset=utf-8'}); res.write("lt;h1gt;你正在访问小六子的服务器lt;/h1gt;"); res.end();});server.listen(8080,function(){ console.log("服务已启动");});


3. 异步示例截图

当服务启动时,它看起来像这样:


发起请求时,返回的信息如下:



Promise基础


1. 什么是Promise ?

Promise是一个用于传递异步操作消息的对象。它代表一个事件(通常是一个异步操作),其结果将在未来知道,这个事件为进一步的处理提供了一个统一的API。


2. Promise特点

许诺对象有以下两个特征:

对象的状态不受外界影响。Promise对象代表一个异步操作,有三种状态:Pending(进行中),Resolved(已完成,又称FulFilled)和Rejected(已失败)。只有异步操作的结果,可以决定当前是哪一种状态,任何其他操作都无法改变这个状态。一旦状态改变,就不会再变,任何时候都可以得到这个结果。Promise对象的状态改变,只有两种可能:从Pending变为Resolved和从Pending变为Rejected。只要这两种情况发生,状态就不会再变了,会一直保持这种结果。如果改变已经发生了,你再对Promise对象添加回调函数,也会立即得到这个结果。这与事件(Event)完全不同,事件的特点是,如果你错过了它,再去监听,是得不到结果的。


3. 异步的缺点

异步执行顺序和时间是不可控的,如下所示:

现在假设有两个文件,file1.txt和file2.txt,如下所示:



这两个文件按顺序读取,代码如下:

var fs =require("fs");fs.readFile("./file1.txt",function(err,data){ console.log(data.toString());});fs.readFile("./file2.txt",function(err,data){ console.log(data.toString());});

结果如下:


通过上面的例子,我们不难发现,每次运行得到的结果并不完全一样,有时与我们预期的结果并不一致,这就是异步的不可控性。那么如何解决呢?


4. Promise保证异步顺序

Promise可以保证异步执行的顺序,如下所示:

var p1 = new Promise(function(resolve,reject){ fs.readFile("./file1.txt",function(err,data){ if(err){ reject(err); }else{ resolve(data.toString()); } });});var p2 = new Promise(function(resolve,reject){ fs.readFile("./file2.txt",function(err,data){ if(err){ reject(err); }else{ resolve(data.toString()); } });});//通过数组中的顺序,控制异步输出的顺序Promise.all([p1,p2]).then(function(datas){ console.log(datas);},function(errs){ console.log(errs);});

优化结果如下:


通过上面的例子发现,Promise可以通过消息的传递来保证异步操作的顺序。

关于Node.js的回调函数的基本介绍以及异步和同步的详细说明,本文就到这里了。关于Node.js回调函数同步与异步的更多信息,请搜索源搜网之前的文章或者继续浏览下面的相关文章。

0

精彩评论

暂无评论...
验证码 换一张
取 消