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

目录
  • 回调函数
    • 1. 什么是回调函数?
    • 2. 回调函数实现机制
    • 3. 回调函数用途
    • 4. 回调函数示例
  • 异步与同步
    • 1. 什么是异步与同步?
    • 2. 同步示例
    • 3. 异步示例一
    • 4. 异步示例二
  • 异步的实现
    • 1. 回调函数的同步示例
    • 2. 异步事件示例
    • 3. 异步示例截图
  • Promise基础
    • 1. 什么是Promise ?
    • 2. Promise特点
    • 3. 异步的缺点
    • 4. Promise保证异步顺序

经过前面两天的学习,已经对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回调函数 同步异步内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • 我的Node.js学习之路(三)--node.js作用、回调、同步和异步代码 以及事件循环

    一,node.js的作用, I/O的意义,(I/O是输入/输出的简写,如:键盘敲入文本,输入,屏幕上看到文本显示输出.鼠标移动,在屏幕上看到鼠标的移动.终端的输入,和看到的输出.等等)   node.js想解决的问题,(处理输入,输入,高并发 .如 在线游戏中可能会有上百万个游戏者,则有上百万的输入等等)(node.js适合的范畴:当应用程序需要在网络上发送和接收数据时Node.js最为适合.这可能是第三方的API,联网设备或者浏览器与服务器之间的实时通信)   并发的意义,(并发这个术语描述的

  • Node.js 回调函数实例详解

    Node.js 回调函数 阻塞与非阻塞 node.js 异步编程的直接体现就是回调. 异步编程依托于回调来实现,但不能说使用了回调后程序就异步化了. 回调函数在完成任务后就会被调用,Node 使用了大量的回调函数,Node 所有 API 都支持回调函数. 阻塞代码实例(同步函数) //阻塞是按顺序执行的 var fs = require("fs"); var data = fs.readFileSync('input.txt'); console.log(data.toString()

  • 深入理解Node.js 事件循环和回调函数

    本文详细的介绍了Node.js 事件循环和Node.js回调函数,废话不多说了,具体看下面把.  一.Node.js 事件循环 Node.js 是单进程单线程应用程序,但是通过事件和回调支持并发,所以性能非常高.Node.js 的每一个 API 都是异步的,并作为一个独立线程运行,使用异步函数调用,并处理并发.Node.js 基本上所有的事件机制都是用设计模式中观察者模式实现.Node.js 单线程类似进入一个while(true)的事件循环,直到没有事件观察者退出,每个异步事件都生成一个事件观

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

    目录 回调函数 1. 什么是回调函数? 2. 回调函数实现机制 3. 回调函数用途 4. 回调函数示例 异步与同步 1. 什么是异步与同步? 2. 同步示例 3. 异步示例一 4. 异步示例二 异步的实现 1. 回调函数的同步示例 2. 异步事件示例 3. 异步示例截图 Promise基础 1. 什么是Promise ? 2. Promise特点 3. 异步的缺点 4. Promise保证异步顺序 经过前面两天的学习,已经对Node.js有了一个初步的认识,今天继续学习其他内容,并加以整理分享,

  • Node.js基础入门之缓存区与文件操作详解

    目录 缓存区 1. 什么是缓存区? 2. 创建指定长度的缓存区 3. 通过数组创建缓存区 4. 通过字符串创建缓存区 5. 读写缓存区 6. 复制缓存区 文件操作 1. 异步直接读取 2. 同步直接读取 3. 流式读取 4. 写入文件 5. 流式写入文件 6. 读取文件信息 7. 删除文件 8. 管道 9. 链式流 经过前面三天的学习,Node.js的基础知识已逐渐掌握,今天继续学习缓存区和文件操作,并稍加整理加以分享,如有不足之处,还请指正. 缓存区 1. 什么是缓存区? JavaScript

  • Node.js基础入门之模块与npm包管理器使用详解

    目录 require函数 模块分类 第三方模块 1. 安装第三方模块 2. 引入第三方模块 3. 示例测试 系统模块 require注意事项 exports导出对象 1. exports示例 2. exports注意事项 module模块对象 package.json包描述文件 1. 什么是package.json ? 2. 如何创建package.json文件? NPM基础 1. 常用npm命令 2. npm 示例 cnpm基础 1. 什么是cnpm ? 2. 使用cnpm 控制台输出 1.

  • Node.js基础入门之使用方式及模块化详解

    目录 什么是Node.js ? Node.js下载 Node.js和JavaScript的区别 Node.js安装与验证 Node.js使用方式 1. REPL模式 2. 文件模式 Node.js模块化 1. 什么是模块? 2. 模块分类 3. 创建自定义模块 4. 调用自定义模块 5. 模块测试 6. 主模块 7. 模块组成 在这个竞争日益激烈的今天,已经不是一门语言,一项技术走天下的时代了.正所谓艺多不压身,今天开始学习Node.js,学而时习之,不亦乐乎,希望可以借鉴经验,学以致用,如有不

  • Node.js基础入门之path模块,url模块,http模块使用详解

    目录 path模块 1. path模块示例 2. path模块其他方法 url模块 1. 旧的解析方法 2. 新的解析方法 http模块 1. 什么是HTTP协议? 2. HTTP协议约束的细节 3. HTTP请求响应过程 4. http模块get方法 经过前面四天的学习,对Node.js已经有了一个基础的认识,今天继续学习Node.js网络通信编程相关内容,并稍加整理加以分享,如有不足之处,还请指正. path模块 Node.js中,提供了一个path模块,在这个模块中,提供了许多实用的,可被

  • js基础之DOM中元素对象的属性方法详解

    在 HTML DOM (文档对象模型)中,每个部分都是节点. 节点是DOM结构中最基本的组成单元,每一个HTML标签都是DOM结构的节点. 文档是一个    文档节点 . 所有的HTML元素都是    元素节点 所有 HTML 属性都是    属性节点 文本插入到 HTML 元素是    文本节点 注释是    注释节点. 最基本的节点类型是Node类型,其他所有类型都继承自Node,DOM操作往往是js中开销最大的部分,因而NodeList导致的问题最多.要注意:NodeList是'动态的',

  • 使用 Node.js 实现图片的动态裁切及算法实例代码详解

    背景&概览 目前常见的图床服务都会有图片动态裁切的功能,主要的应用场景用以为各种终端和业务形态输出合适尺寸的图片. 一张动辄以 MB 为计量单位的原始大图,通常不会只设置一下显示尺寸就直接输出到终端中,因为体积太大加载体验会很差,除了影响加载速度还会增加终端设备的内存占用.所以要想在各种终端下都能保证图片质量的同时又确保输出合适的尺寸,那么此时就需要根据图片 URL 来对原始图片进行裁切,然后动态生成并输出一张新的图片. URL 的设计 图片 URL 需要包含图片 id.尺寸.质量等信息.有两种

  • Node.js实战之Buffer和Stream模块系统深入剖析详解

    目录 正文 写入缓冲区 从流中读取数据 管道流 链式流 模块系统 正文 JavaScript语言本身只有字符串数据类型,没有二进制数据类型. 但是,在处理TCP流或文件流时必须使用二进制数据. 因此,在node JS中,定义了一个缓冲区类来创建用于存储二进制数据的缓冲区. const buf = Buffer.from('runoob', 'ascii'); 在node JS中,缓冲区类是与node内核一起发布的核心库. 缓冲库是node JS带来的一种存储原始数据的方法,它允许节点JS. co

  • 安装node.js以及搭建vue项目过程中遇到的问题详解

    目录 一.node.js安装 二.如何找node.js历史版本 1.点击DOWNLOADS 2.点击页面下方 3.翻页找到历史版本 三.检查是否安装成功? 四.安装成功后需要配置环境变量: 五.环境搭建 六.项目创建 总结 一.node.js安装 进入官网 https://nodejs.org/en/download/ 直接点击下载安装!安装过程直接下一步就行: 二.如何找node.js历史版本 (https://nodejs.org/en/download/) 1.点击DOWNLOADS 2.

随机推荐