Node.js基础入门之回调函数及异步与同步详解

 更新时间:2022年03月21日 15:05:14   作者:小六公子  
Node.js是一个基于Chrome V8引擎的JavaScript运行时。类似于Java中的JRE,.Net中的CLR。本文将详细为大家介绍Node.js中的回调函数及异步与同步,感兴趣的可以了解一下

经过前面两天的学习,已经对Node.js有了一个初步的认识,今天继续学习其他内容,并加以整理分享,如有不足之处,还请指正。

回调函数

1. 什么是回调函数?

回调函数,或简称回调【callback】将一个A函数作为参数传入另一个B函数中,B函数在执行过程中,根据时机或条件决定是否调用A函数,A函数就是B函数的回调函数。

2. 回调函数实现机制

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

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

3. 回调函数用途

回调函数在JavaScript中使用非常多,最简单的场景就是事件注册或异步函数。如:当用户点击某个按钮时,需要做出相应的响应,那么就会用到回调函数。

4. 回调函数示例

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

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

执行结果,如下所示:

关于setInterval的参数说明,如下所示:

异步与同步

1. 什么是异步与同步?

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

异步:每一个任务有一个或多个回调函数(callback),前一个任务结束后,不是执行后一个任务,而是执行回调函数,后一个任务则是不等前一个任务结束就开始执行,所以程序的执行顺序与任务的排列顺序是不一致的,异步的。

2. 同步示例

同步即按顺序执行,存在先后顺序,如下所示:

console.log("1111");
console.log("2222");
console.time("t1");
for(var i=0;i<1000000;i++){

}
console.timeEnd("t1");
console.log("3333");

同步执行结果,如下所示:

3. 异步示例一

异步则是采用回调函数执行,如下所示:

console.log("1111");
console.log("2222");
setTimeout(function(){
    console.time("t1");
    for(var i=0;i<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;i<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("<h1>你正在访问小六子的服务器</h1>");
    res.end();
});
server.listen(8080,function(){
    console.log("服务已启动");
});

3. 异步示例截图

当服务启动时,如下所示:

当发起请求时,返回信息如下所示:

Promise基础

1. 什么是Promise ?

Promise(承诺)就是一个对象,用来传递异步操作的消息。它代表了某个未来才会知道的结果的事件(通常是一个异步操作),并且这个事件提供统一的API,可供进一步处理。

2. Promise特点

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回调函数 同步异步内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • 使用 Node.js 对文本内容分词和关键词抽取

    使用 Node.js 对文本内容分词和关键词抽取

    这篇文章主要介绍了使用 Node.js 对文本内容分词和关键词抽取,需要的朋友可以参考下
    2017-05-05
  • 查询Node.js版本信息的六种方法

    查询Node.js版本信息的六种方法

    随着应用程序规模越来越庞大,Node.js版本的更新也日益频繁,本文主要介绍了查询Node.js版本信息的六种方法,具有一定的参考价值,感兴趣的可以了解一下
    2024-03-03
  • NodeJs读取JSON文件格式化时的注意事项

    NodeJs读取JSON文件格式化时的注意事项

    本文是作者在进行NodeJs开发时偶然发现的问题,经过一番努力,最终找到解决方案,分享给大家,有需要的小伙伴可以参考下
    2016-09-09
  • 详解如何查看node端口被占用并杀死

    详解如何查看node端口被占用并杀死

    这篇文章主要给大家介绍了如何查看node端口被占用并杀死,文中给出了相关的解决方法,并通过代码示例给大家介绍的非常详细,对前端开发要学会如何查看端口占用并杀死非常有用,需要的朋友可以参考下
    2024-01-01
  • Node.JS中事件轮询(Event Loop)的解析

    Node.JS中事件轮询(Event Loop)的解析

    对NodeJs的事情轮询机造一孔之见。查阅了些许材料后,总算掀开了其神奇的里纱。下面这篇文章主要介绍了Node.JS中事件轮询(Event Loop)的相关资料,需要的朋友可以参考借鉴,下面来一起看看吧。
    2017-02-02
  • 通过实例了解Nodejs模块系统及require机制

    通过实例了解Nodejs模块系统及require机制

    这篇文章主要介绍了通过实例了解Nodejs模块系统及require机制,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2020-07-07
  • node.js 抓取代理ip实例代码

    node.js 抓取代理ip实例代码

    这篇文章主要介绍了node.js 抓取代理ip实例代码的相关资料,需要的朋友可以参考下
    2017-04-04
  • electron demo项目npm install安装失败的解决方法

    electron demo项目npm install安装失败的解决方法

    下面小编就为大家分享一篇electron demo项目npm install安装失败的解决方法,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2018-02-02
  • 解析NodeJs的调试方法

    解析NodeJs的调试方法

    本文主要介绍了NodeJs调试的步骤,以及实例方法,具有一定的参考作用,需要的朋友可以看下
    2016-12-12
  • Node在Controller层进行数据校验的过程详解

    Node在Controller层进行数据校验的过程详解

    这篇文章主要给大家介绍了关于Node在Controller层进行数据校验的相关资料,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2020-08-08

最新评论