Node.js基础入门第三天

简介: Node.js基础入门第三天

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

回调函数

1. 什么是回调函数?

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

2. 回调函数实现机制

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

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

3. 回调函数用途

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

4. 回调函数示例

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

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

执行结果,如下所示:

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

异步与同步

1. 什么是异步与同步?

  1. 同步:一个任务等待前一个任务结束,然后再执行,程序的执行顺序与任务的排列顺序是一致的,同步的。
  2. 异步:每一个任务有一个或多个回调函数(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的注意事项,如下所示:

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

关于主线程和任务线程的执行顺序,可参考下图:

异步的实现

在Node.js中,异步共有三种实现方式:

  1. 回调函数,回调函数不一定是异步,但是异步一定有回调函数。
  2. 事件【基于回调】
  3. 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对象有以下两个特点:

  1. 对象的状态不受外界影响。Promise对象代表一个异步操作,有三种状态:Pending(进行中),Resolved(已完成,又称FulFilled)和Rejected(已失败)。只有异步操作的结果,可以决定当前是哪一种状态,任何其他操作都无法改变这个状态。
  2. 一旦状态改变,就不会再变,任何时候都可以得到这个结果。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可以通过消息的传递,保证异步操作的顺序。

备注

观沧海【作者】曹操 【朝代】东汉末年/三国

东临碣石,以观沧海。水何澹澹,山岛竦峙。

树木丛生,百草丰茂。秋风萧瑟,洪波涌起。

日月之行,若出其中;星汉灿烂,若出其里。

幸甚至哉,歌以咏志。

相关文章
|
1月前
|
前端开发 机器人 API
前端大模型入门(一):用 js+langchain 构建基于 LLM 的应用
本文介绍了大语言模型(LLM)的HTTP API流式调用机制及其在前端的实现方法。通过流式调用,服务器可以逐步发送生成的文本内容,前端则实时处理并展示这些数据块,从而提升用户体验和实时性。文章详细讲解了如何使用`fetch`发起流式请求、处理响应流数据、逐步更新界面、处理中断和错误,以及优化用户交互。流式调用特别适用于聊天机器人、搜索建议等应用场景,能够显著减少用户的等待时间,增强交互性。
291 2
|
16天前
|
机器学习/深度学习 自然语言处理 前端开发
前端神经网络入门:Brain.js - 详细介绍和对比不同的实现 - CNN、RNN、DNN、FFNN -无需准备环境打开浏览器即可测试运行-支持WebGPU加速
本文介绍了如何使用 JavaScript 神经网络库 **Brain.js** 实现不同类型的神经网络,包括前馈神经网络(FFNN)、深度神经网络(DNN)和循环神经网络(RNN)。通过简单的示例和代码,帮助前端开发者快速入门并理解神经网络的基本概念。文章还对比了各类神经网络的特点和适用场景,并简要介绍了卷积神经网络(CNN)的替代方案。
|
16天前
|
移动开发 前端开发 JavaScript
前端实训,刚入门,我用原生技术(H5、C3、JS、JQ)手写【网易游戏】页面特效
于辰在大学期间带领团队参考网易游戏官网的部分游戏页面,开发了一系列前端实训作品。项目包括首页、2021校园招聘页面和明日之后游戏页面,涉及多种特效实现,如动态图片切换和人物聚合效果。作品源码已上传至CSDN,视频效果可在CSDN预览。
25 0
前端实训,刚入门,我用原生技术(H5、C3、JS、JQ)手写【网易游戏】页面特效
|
24天前
|
监控 前端开发 JavaScript
React 静态网站生成工具 Next.js 入门指南
【10月更文挑战第20天】Next.js 是一个基于 React 的服务器端渲染框架,由 Vercel 开发。本文从基础概念出发,逐步探讨 Next.js 的常见问题、易错点及解决方法,并通过具体代码示例进行说明,帮助开发者快速构建高性能的 Web 应用。
61 10
|
22天前
|
数据采集 存储 JavaScript
如何使用Puppeteer和Node.js爬取大学招生数据:入门指南
本文介绍了如何使用Puppeteer和Node.js爬取大学招生数据,并通过代理IP提升爬取的稳定性和效率。Puppeteer作为一个强大的Node.js库,能够模拟真实浏览器访问,支持JavaScript渲染,适合复杂的爬取任务。文章详细讲解了安装Puppeteer、配置代理IP、实现爬虫代码的步骤,并提供了代码示例。此外,还给出了注意事项和优化建议,帮助读者高效地抓取和分析招生数据。
如何使用Puppeteer和Node.js爬取大学招生数据:入门指南
|
2月前
|
JavaScript 前端开发 小程序
一小时入门Vue.js前端开发
本文是作者关于Vue.js前端开发的快速入门教程,包括结果展示、参考链接、注意事项以及常见问题的解决方法。文章提供了Vue.js的基础使用介绍,如何安装和使用cnpm,以及如何解决命令行中遇到的一些常见问题。
一小时入门Vue.js前端开发
|
1月前
|
存储 JavaScript 前端开发
前端开发:Vue.js入门与实战
【10月更文挑战第9天】前端开发:Vue.js入门与实战
|
1月前
|
自然语言处理 JavaScript 前端开发
JavaScript高级——ES6基础入门
JavaScript高级——ES6基础入门
24 1
|
1月前
|
机器学习/深度学习 自然语言处理 前端开发
前端大模型入门:Transformer.js 和 Xenova-引领浏览器端的机器学习变革
除了调用API接口使用Transformer技术,你是否想过在浏览器中运行大模型?Xenova团队推出的Transformer.js,基于JavaScript,让开发者能在浏览器中本地加载和执行预训练模型,无需依赖服务器。该库利用WebAssembly和WebGPU技术,大幅提升性能,尤其适合隐私保护、离线应用和低延迟交互场景。无论是NLP任务还是实时文本生成,Transformer.js都提供了强大支持,成为构建浏览器AI应用的核心工具。
460 1
|
1月前
|
Web App开发 JSON JavaScript
深入浅出:Node.js后端开发入门与实践
【10月更文挑战第4天】在这个数字信息爆炸的时代,了解如何构建一个高效、稳定的后端系统对于开发者来说至关重要。本文将引导你步入Node.js的世界,通过浅显易懂的语言和逐步深入的内容组织,让你不仅理解Node.js的基本概念,还能掌握如何使用它来构建一个简单的后端服务。从安装Node.js到实现一个“Hello World”程序,再到处理HTTP请求,文章将带你一步步走进Node.js的大门。无论你是初学者还是有一定经验的开发者,这篇文章都将为你打开一扇通往后端开发新世界的大门。