nodejs学习步骤

1 命令行窗口

1.1. 命令行窗口(小黑屏)、CMD窗口、终端、shell

开始菜单 -> 运行 -> cmd -> 回车

直接url栏中输入cmd

1.2. 常用指令

dir 列出当前目录下面的所有文件

cd 目录名 进入到指定的目录

md 目录名 创建一个文件夹

rd 目录名 删除一个文件夹

文件名.后缀名 打开文件

D: 进入D盘

1.3. 目录

. 表示当前目录

.. 表示上一级目录

1.4. 环境变量(windows系统中变量)

path:环境变量中保存的是一个一个的路径,路径之间使用;隔开

里面放的都是路径,该路径下的文件,可以直接打开

作用:当我们在命令行窗口打开一个文件,或调用一个程序时,系统会首选在当前目录下寻找文件程序,如果找到了则直接打开,如果没有找到则会依次到环境变量path的路径中寻找,直到找到为止,如果没有找到则报错。

所以我们可以将一些经常需要访问的程序和文件的路径添加到path中,这样我们就可以在任意位置来访问这些文件和程序了。

2 进程和线程

2.1. 进程

进程负责为程序的运行提供必备的环境。

进程就相当于工厂中的车间。

2.2. 线程

线程是计算机中的最小的计算单位,线程负责执行进程中的程序。

线程就相当于工厂中的工人。

2.3. 单线程

js是单线程的。

2.4. 多线程

java是多线程的。

3 Nodejs

是一个能够在服务器端运行JavaScript的开放源代码、跨平台JavaScript运行环境。

采用Google开发的V8引擎运行js代码,使用事件驱动、非阻塞和异步I/O模型等技术来提高性能,可优化应用程序的传输量和规模。

3.1. I/O(Input/Output)

I/O操作指的是对磁盘的读写操作

3.2. Node

Node是对ES标准的一种实现,Node也是一个JS引擎

通过Node可以使js代码再服务器端运行

Node仅仅对ES标准进行了实现,所以在Node中不包含DOM 和 BOM

Node中可以使用ES所有的内建对象

(1) String Number Boolean Math Date RegExp Function Object Array

(2) 可以使用 console 也可以使用定时器(setTimeout() setInterval())

Node 可以在后台来编写服务器

Node编写服务器都是单线程的服务器

(1) 进程就是一个一个的工作计划(工厂中的车间)

(2) 线程是计算机最小的运算单位(工厂中的工人)

(3) 线程是干活的

传统的服务器都是多线程的

(1) 每进来一个请求,就创建一个线程去处理请求

Node的服务器是单线程的

(1) Node处理请求时是单线程,但是在后台拥有一个I/O线程池

运行:node XXX.js运行

3.3. 为什么选择Node

使用JavaScript语法开发后端应用

一些公司要求前端工程师掌握Node开发

生态系统活跃,有大量开源库可以使用

前端开发工具大多基于Node开发

3.4. Node是什么

Node是一个基于Chrome V8引擎的JavaScript代码运行环境。

浏览器(软件)能够运行JavaScript代码,浏览器就是JavaScript代码的运行环境

Node(软件)能够运行JavaScript代码,Node就是JavaScript代码的运行环境

官网:https://nodejs.org/en/

LTS = Long Term Support 长期支持版 稳定版

Current 拥有最新特性 实验版

3.5. Node.js 的组成

JavaScript 由三部分组成,ECMAScript,DOM,BOM。

Node.js是由ECMAScript及Node 环境提供的一些附加API组成的,包括文件、网络、路径等等一些更加强大的 API。(ECMAScript + Node模块API)

4 模块化

JavaScript开发弊端:

JavaScript在使用时存在两大问题,文件依赖和命名冲突。

软件中的模块化开发:

一个功能就是一个模块,多个模块可以组成完整应用,抽离一个模块不会影响其他功能的运行。

4.1. 模块化

将一个完整的程序分成一个一个小的程序,降低耦合度,方便代码的复用。

在node中,一个js文件就是一个模块。

在node中,每一个js文件中的js代码 都是独立运行在一个函数中

(function(){

....

})()

而不是全局作用域,所以一个模块中的变量和函数在其他模块中无法访问。

我们可以通过 exports 来向外部暴露变量和方法,只需要将需要暴露给外部的变量或方法设置为exports的属性即可。

exports.x = 100

exports.fn = function(){}

Node.js规定一个JavaScript文件就是一个模块,模块内部定义的变量和函数默认情况下在外部无法得到。

模块内部可以使用exports对象进行成员导出,使用require方法导入其他模块。

4.2. 引入其他的模块

在node中,通过require()函数来引入外部的模块。

require() 可以传递一个文件的路径作为参数,node将会自动根据该路径来引入外部模块。

这里路径,如果使用相对路径,必须以.或..开头。

使用require()引入模块以后,该函数会返回一个对象,这个对象代表的是引入的模块。

4.3. 模块标识

我们使用require()引入外部模块时,使用的就是模块标识。

require( './02module.js ') './02module.js'这个路径就是一个模块标识。

我们可以通过模块标识来找到指定的模块。

模块分成两大类:

核心模块

由node引擎提供的模块

核心模块的标识就是模块的名字 (或者npm下载的模块,都是直接写名字)

文件模块

由用户自己创建的模块

文件模块的标识就是文件的路径 (可以是绝对路径 或 相对路由)相对路径使用 . 或 .. 开头。

4.4. 什么是系统模块

Node运行环境提供的API. 因为这些API都是以模块化的方式进行开发的, 所以我们又称Node运行环境提供的API为系统模块

4.4.1. 系统模块fs 文件操作:

f:file 文件 ,s:system 系统,文件系统。

const fs = require('fs');

读取文件内容

fs.readFile('文件路径/文件名称'[,'文件编码'], callback);

写入文件内容

fs.writeFile('文件路径/文件名称', '数据', callback);

const content = '<h3>正在使用fs.writeFile写入文件内容</h3>';

fs.writeFile('../index.html', content, err => {

if (err != null) {

console.log(err);

return;

}

console.log('文件写入成功');

});

4.4.2. 系统模块path 路径操作:

为什么要进行路径拼接

不同操作系统的路径分隔符不统一

/public/uploads/avatar

Windows 上是 \ /

Linux 上是 /

路径拼接语法:

path.join('路径', '路径', ...)

// 导入path模块

const path = require('path');

// 路径拼接

let finialPath = path.join('itcast', 'a', 'b', 'c.css');

// 输出结果 itcast\a\b\c.css

console.log(finialPath);

相对路径VS绝对路径:

大多数情况下使用绝对路径,因为相对路径有时候相对的是命令行工具的当前工作目录

在读取文件或者设置文件路径时都会选择绝对路径

使用__dirname获取当前文件所在的绝对路径

4.5. 什么是第三方模块

别人写好的、具有特定功能的、我们能直接使用的模块即第三方模块,由于第三方模块通常都是由多个文件组成并且被放置在一个文件夹中,所以又名包。

第三方模块有两种存在形式:

以js文件的形式存在,提供实现项目具体功能的API接口。

以命令行工具形式存在,辅助项目开发。

npmjs.com:第三方模块的存储和分发仓库。

4.5.1. 第三方模块 nodemon

nodemon是一个命令行工具,用以辅助项目开发。

在Node.js中,每次修改文件都要在命令行工具中重新执行该文件,非常繁琐。

使用步骤:

使用npm install nodemon –g 下载它

在命令行工具中用nodemon命令替代node命令执行文件

5 global

5.1. 全局变量

在node中有一个全局变量 global, 它的作用和网页中window类似。

在全局中创建的变量都会作为global的属性保存。

在全局中创建的函数都会作为global的方法保存。

console.log(global);

Node中全局对象下有以下方法,可以在任何地方使用,global可以省略。

console.log() 在控制台中输出

setTimeout() 设置超时定时器

clearTimeout() 清除超时时定时器

setInterval() 设置间歇定时器

clearInterval() 清除间歇定时器

5.2. 模块作用域

当node在执行模块中的代码时,它会首先在代码的最顶部,添加如下代码

function (exports, require, module, __filename, __dirname) {

在代码的最底部,添加如下代码

}

实际上模块中的代码都是包装在一个函数中执行的,并且在函数执行时,同时传递进了5个实参

exports 该对象用来将变量或函数暴露到外部

require 函数,用来引入外部模块

module 代表的是当前模块本身 exports就是module的属性

既可以使用 exports 导出,也可以使用module.exports 导出

__filename 当前模块的完整路径

__dirname 当前模块所在文件夹的完整路径

查看的方式:

console.log(arguments);

arguments.callee:保存的是当前执行的函数的对象

console.log(arguments.callee+'');

console.log(module.exports == exports);

console.log(__filename);

console.log(__dirname);

5.2.1. exports 和 module.exports

exports 实际指向 module.exports。

通过exports只能使用.的方式来向外暴露内部变量

exports.xxx = xxx

而module.exports既可以通过.的形式,也可以直接赋值

module.exports.xxx = xxx

module.exports = {}

6 包

6.1. 什么是包

包规范允许我们将一组相关的模块组合到一起,形成一组完整的工具。

包规范由 包结构 和 包描述文件 两个部分组成。

包结构:用于组织包中的各种文件。

包描述文件:描述包的相关信息,以供外部读取分析。

6.2. 包结构

包实际上就是一个压缩文件,解压以后还原目录。符合规范的目录,应该包含如下文件:

package.json 描述文件

bin 可执行二进制文件

lib js代码

doc 文档

test 单元测试

6.3. 描述文件

package.json

项目描述文件,记录了当前项目信息,例如项目名称、版本、作者、github地址、当前项目依赖了哪些第三方模块等。

使用npm init -y命令生成。

项目依赖:

在项目的开发阶段和线上运营阶段,都需要依赖的第三方包,称为项目依赖。

使用npm install 包名命令下载的文件会默认被添加到 package.json 文件的 dependencies 字段中。

在项目的开发阶段需要依赖,线上运营阶段不需要依赖的第三方包,称为开发依赖。

使用npm install 包名 --save-dev命令将包添加到package.json文件的devDependencies字段中。

dependencies 依赖 当前包依赖的其他包

devDependencies 开发环境依赖

package-lock.json文件的作用:

锁定包的版本,确保再次下载时不会因为包版本不同而产生问题。

加快下载速度,因为该文件中已经记录了项目所依赖第三方包的树状结构和包的下载地址,重新安装时只需下载即可,不需要做额外的工作。

6.4. NPM

6.4.1. NPM(Node Package Manager)

npm 帮助其完成了第三方模块的发布、安装和依赖等。

借助NPM,Node与第三方模块之间形成了很好的一个生态系统。

命令:

npm -v :查看npm的版本

npm version :查看所有模块的版本

npm :帮助说明

npm search 包名 :搜索模块包

npm install/i 包名 :在当前目录安装包

npm install/i 包名 -g :全局模式安装包 (全局安装的包一般都是一些工具)

npm remove/r 包名 :删除一个模块

npm uninstall 包名 :删除一个模块

npm update :升级全部包

npm update 包名 :升级指定包

npm install 包名 --save :安装包并添加到依赖中 重要

npm install :下载当前项目所依赖的包

npm install 文件路径 :从本地安装

npm install 包名 --registry=地址 :从镜像源安装

npm config set registry 地址 :设置镜像源

npm install -g 就是npm install --global

npm install -D 就是npm install --save-dev

(1) devDependencies 里面的包只用于开发环境,不用于生产环境

npm install -S 就是npm install --save

(1) 而 dependencies 是需要发布到生产环境的

npm view 包名 versions 查看所有版本 npm view 包名 version 查看最高版本

npm i 包名@版本 安装指定版本的包

全局安装与本地安装:

命令行工具:全局安装

库文件:本地安装

6.4.2. cnpm中国 npm 镜像的客户端

npm install cnpm -g :安装cnpm(cnpm 是中国 npm 镜像的客户端)

npm install cnpm -g --registry=https://registry.npm.taobao.org (国内安装)

6.4.3. npm修改或切换镜像地址

方式一:直接编辑npm的配置文件

npm config edit

直接修改registry的地址

registry=https://registry.npm.taobao.org

方式二:用代码更改npm的配置文件

npm config set registry http://registry.npm.taobao.org

这段代码即将镜像改为淘宝镜像

方式三:使用nrm管理registry地址

安装nrm

npm install -g nrm

查看镜像列表

nrm ls

nrm ls 报错解决方案:

//const NRMRC = path.join(process.env.HOME, '.nrmrc');(注掉)

const NRMRC = path.join(process.env[(process.platform == 'win32') ? 'USERPROFILE' : 'HOME'], '.nrmrc');

切换镜像

nrm use taobao

在nrm添加自己的镜像地址

nrm add r_name r_url

删除

nrm del r_name

测试镜像的相应速度

nrm test r_namer

6.4.4. yarn

方式一:使用安装包安装

官方下载安装包,https://yarnpkg.com/zh-Hans/docs/install,安装完毕后,一定要配置环境变量。

方式二:使用npm安装

npm i yarn -g

常用命令:

yarn / yarn install 等同于npm install 批量安装依赖

yarn add xxx 等同于 npm install xxx --save 安装指定包到指定位置

yarn remove xxx 等同于 npm uninstall xxx --save 卸载指定包

yarn add xxx --dev 等同于 npm install xxx --save-dev

yarn upgrade 等同于 npm update 升级全部包

yarn global add xxx 等同于 npm install xxx -g 全局安装指定包

6.4.5. npx

npm 从5.2版开始,增加了 npx 命令。

Node 自带 npm 模块,所以可以直接使用 npx 命令。万一不能用,就要手动安装一下。

npm install -g npx

调用项目安装的模块:

npx 想要解决的主要问题,就是调用项目内部安装的模块。

npm install -D mocha

一般来说,调用 Mocha ,只能在项目脚本和 package.json 的scripts字段里面, 如果想在命令行下调用,必须像下面这样。

node-modules/.bin/mocha --version

npx 就是想解决这个问题,让项目内部安装的模块用起来更方便,只要像下面这样调用就行了。

npx mocha --version

npx 的原理很简单,就是运行的时候,会到node_modules/.bin路径和环境变量$PATH里面,检查命令是否存在。

由于 npx 会检查环境变量$PATH,所以系统命令也可以调用。

npx ls

注意,Bash 内置的命令不在$PATH里面,所以不能用。比如,cd是 Bash 命令,因此就不能用npx cd。

避免全局安装模块:

除了调用项目内部模块,npx 还能避免全局安装的模块。比如,create-react-app这个模块是全局安装,npx 可以运行它,而且不进行全局安装。

npx create-react-app my-react-app

上面代码运行时,npx 将create-react-app下载到一个临时目录,使用以后再删除。所以,以后再次执行上面的命令,会重新下载create-react-app。

下载全局模块时,npx 允许指定版本。

npx uglify-js@3.1.0 main.js -o ./dist/main.js

上面代码指定使用 3.1.0 版本的uglify-js压缩脚本。

注意,只要 npx 后面的模块无法在本地发现,就会下载同名模块。比如,本地没有安装http-server模块,下面的命令会自动下载该模块,在当前目录启动一个 Web 服务。

npx http-server

--no-install 参数和--ignore-existing 参数:

如果想让 npx 强制使用本地模块,不下载远程模块,可以使用--no-install参数。如果本地不存在该模块,就会报错。

npx --no-install http-server

反过来,如果忽略本地的同名模块,强制安装使用远程模块,可以使用--ignore-existing参数。比如,本地已经全局安装了create-react-app,但还是想使用远程模块,就用这个参数。

npx --ignore-existing create-react-app my-react-app

使用不同版本的 node:

利用 npx 可以下载模块这个特点,可以指定某个版本的 Node 运行脚本。它的窍门就是使用 npm 的 node 模块。

npx node@0.12.8 -v

上面命令会使用 0.12.8 版本的 Node 执行脚本。原理是从 npm 下载这个版本的 node,使用后再删掉。

某些场景下,这个方法用来切换 Node 版本,要比 nvm 那样的版本管理器方便一些。

-p 参数:

-p参数用于指定 npx 所要安装的模块,所以上一节的命令可以写成下面这样。

npx -p node@0.12.8 node -v

上面命令先指定安装node@0.12.8,然后再执行node -v命令。

-p参数对于需要安装多个模块的场景很有用。

npx -p lolcatjs -p cowsay [command]

-c 参数:

如果 npx 安装多个模块,默认情况下,所执行的命令之中,只有第一个可执行项会使用 npx 安装的模块,后面的可执行项还是会交给 Shell 解释。

npx -p lolcatjs -p cowsay 'cowsay hello | lolcatjs'

上面代码中,cowsay hello | lolcatjs执行时会报错,原因是第一项cowsay由 npx 解释,而第二项命令localcatjs由 Shell 解释,但是lolcatjs并没有全局安装,所以报错。

-c参数可以将所有命令都用 npx 解释。有了它,下面代码就可以正常执行了。

npx -p lolcatjs -p cowsay -c 'cowsay hello | lolcatjs'

-c参数的另一个作用,是将环境变量带入所要执行的命令。举例来说,npm 提供当前项目的一些环境变量,可以用下面的命令查看。

npm run env | grep npm_

-c参数可以把这些 npm 的环境变量带入 npx 命令。

npx -c 'echo "$npm_package_name"'

上面代码会输出当前项目的项目名。

执行 GitHub 源码:

npx 还可以执行 GitHub 上面的模块源码。

执行 Gist 代码

npx https://gist.github.com/zkat/4bc19503fe9e9309e2bfaa2c58074d32

执行仓库代码

npx github:piuccio/cowsay hello

注意,远程代码必须是一个模块,即必须包含package.json和入口脚本。

6.5. Node.js中模块加载机制

模块查找规则-当模块拥有路径但没有后缀时:

require('./find.js');

require('./find');

require方法根据模块路径查找模块,如果是完整路径,直接引入模块。

如果模块后缀省略,先找同名JS文件再找同名JS文件夹。

如果找到了同名文件夹,找文件夹中的index.js。

如果文件夹中没有index.js就会去当前文件夹中的package.json文件中查找main选项中的入口文件。

如果找指定的入口文件不存在或者没有指定入口文件就会报错,模块没有被找到。

模块查找规则-当模块没有路径且没有后缀时:

require('find');

Node.js会假设它是系统模块。

Node.js会去node_modules文件夹中。

首先看是否有该名字的JS文件。

再看是否有该名字的文件夹。

如果是文件夹看里面是否有index.js。

如果没有index.js查看该文件夹中的package.json中的main选项确定模块入口文件。

否则找不到报错。

7 文件系统

7.1. Buffer(缓冲区)

Buffer的结构和数组很像,操作的方法也和数组类似

数组中不能存储二进制文件,而Buffer就是专门用来存储二进制数据

使用buffer不需要引入模块,直接使用即可

在buffer中存储的都是二进制数据,但是在显示时都是以16进制的形式显示

buffer中每一个元素的范围是从 00 - ff 0 - 255

00000000 - 11111111

计算机中 一个0 或 一个1 我们称为1位(bit)

8bit = 1byte(字节)

1024byte = 1kb

1024kb = 1mb

1024mb = 1gb

1024gb = 1tb

buffer中的一个元素,占用内存中的一个字节

buffer的大小一旦确定,则不能修改,buffer实际上是对底层内存的直接操作

Buffer.from(str) 将一个字符串转换位为Buffer

Buffer.alloc(size) 创建一个指定大小的Buffer(并将内存中的数据清空)

Buffer.allocUnsafe(size) 创建一个指定大小的Buffer,但是可能包含敏感数据(分配空间的时候,没有清空里面的数据,性能会好一些)

buf.toString() 将缓冲区中的数据转换为字符串

buf.length 占用内存的大小

在UTF-8编码中,1个汉字占用3个字节

buf[2] = 0xaa 十六进制数,以0x开头

buf[3] = 556 只能保存8位,前面的会省略掉

buf[2].toString(16) 转16进制

buf3[2].toString(2) 转2进制

7.2. 文件系统

文件系统(File System)

文件系统简单来说就是通过node来操作系统中的文件

使用文件系统,需要先引入fs模块,fs是核心模块,直接引入不需要下载

fs模块中所有的操作都有两种形式可供选择 同步和异步。

同步文件系统会阻塞程序的执行,也就是除非操作完毕,否则不会向下执行代码。

异步文件系统不会阻塞程序的执行,而是在操作完成时,通过回调函数将结果返回。

7.3. 文件的写入

步骤:

打开文件

fs.openSync(path[, flags, mode])

- path 要打开文件的路径

- flags 打开文件要做的操作的类型

- r 只读的

- w 可写的

- mode 设置文件的操作全选,一般不传

返回值:

- 该方法会返回一个文件的描述符作为结果,我们可以通过该描述符来对文件进行各种操作

向文件中写入内容

fs.writeSync(fd, string[, position[, encoding]])

- fd 文件的描述符,需要传递要写入的文件的描述符

- string 要写入的内容

- position 写入的起始位置

- encoding 写入的编码,默认utf-8

保存并关闭文件

fs.closeSync(fd)

- fd 要关闭的文件的描述符

7.4. 异步文件写入

步骤:

打开文件

fs.open(path[, flags[, mode]], callback)

- 用来打开一个文件

- 异步调用的方法,结果都是通过回调函数的参数返回的

- 回调函数两参数:

err 错误对象,如果没有错误则为null

fd 文件的描述符

向文件中写入内容

fs.write(fd, buffer[, offset[, length[, position]]], callback)

- 用来异步写入一个文件

保存并关闭文件

fs.close(fd, callback)

- 用来关闭文件

7.5. 简单文件写入

fs.writeFileSync(file, data[, options])

fs.writeFile(file, data[, options], callback)

- file 要操作的文件的路径

- data 要写入的数据

- options 选项,可以对写入进行一些设置

- flag r 只读 w 可写 a 追加

- callback 当写入完成以后执行的函数

步骤:

引入fs模块

var fs = require('fs')

写入

fs.writeFile('C:\Users\bing\Desktop\hello.txt','内容',{flag:'a'},function(err){

if(!err){

console.log('写入成功~~~');

}else{

console.log(err);

}

})

7.6. 流式文件写入

同步,异步,简单文件的写入都不适合大文件的写入,性能较差,容易导致内存溢出

流式文件写入步骤:

创建一个可写流

var ws = fs.createWriteStream(path[, options])

- 可以用来创建一个可写流

- path,文件路径

- options,配置的参数

可以通过监听流的open和close事件来监听流的打开和关闭

(1) on 和 once 绑定事件

(2) once 可以为对象绑定一个一次性的事件,该事件将会在触发一次以后自动失效

ws.once('open',function(){

console.log('流打开了~~~');

})

ws.once('close',function(){

console.log('流关闭了~~~');

})

通过write方法向文件中输出内容

ws.write('通过可写流写入文件的内容')

ws.write('helloworld')

关闭流

ws.end()

7.7. 简单文件读取

fs.readFileSync(path[, options])

fs.readFile(path[, options], callback)

- path 要读取的文件的路径

- options 读取的选项

- callback 回调函数,通过回调函数将读取的内容返回(err,data)

err 错误对象

data 读取到的数据,会返回一个Buffer

步骤:

引入fs模块

var fs = require('fs')

读取

fs.readFile('gxb.jpg',function(err,data){

if(!err){

// console.log(data);

//将data写入到文件中

fs.writeFile('hello.jpg',data,function(err){

if(!err){

console.log('文件写入成功');

}

})

}

})

7.8. 流式文件读取

流式文件读取也适用于一些较大的文件,可以分多次将文件读取到内存中

步骤1:

//引入fs模块

var fs = require('fs')

//创建一个可读流

var rs = fs.createReadStream('gxb.jpg')

//创建一个可写流

var ws = fs.createWriteStream('hello2.jpg')

//监听流的开启和关闭

rs.once('open',function(){

console.log('可读流打开了~~');

})

rs.once('close',function(){

console.log('可读流关闭了~~');

//数据读取完毕,关闭可写流

ws.end()

})

ws.once('open',function(){

console.log('可写流打开了~~');

})

ws.once('close',function(){

console.log('可写流关闭了~~');

})

//如果要读取一个可读流中的数据,必须要为可读流绑定一个data事件,

//data事件绑定完毕,它会自动开始读取数据

//注意:流式文件读取对象,并不是一次性读取文件的全部数据,而是分多次读取。

//所以,监听data事件,就不能使用once,必须使用on

//once只监听一次事件,on可以连续监听。

rs.on('data',function(data){

// console.log(data);

// console.log(data.length);

// 将读取到的数据写入到可写流中

ws.write(data)

})

步骤2:

//引入fs模块

var fs = require('fs')

//创建一个可读流

var rs = fs.createReadStream('gxb.jpg')

//创建一个可写流

var ws = fs.createWriteStream('hello3.jpg')

//可以将可读流中的内容,直接输出到可写流中

//相当于在这两个对象之间建立的管道,可以直接传输数据。

rs.pipe(ws)

7.9. fs中其他方法

fs.existsSync(path)

- 检查一个文件是否存在

fs.stat(path[, options], callback)

fs.statSync(path[, options])

- 获取文件的状态

- callback 回调函数,它会给我们返回一个对象,这个对象中保存了当前对象状态的相关信息

fs.unlink(path, callback)

fs.unlinkSync(path)

- 删除文件

fs.readdir(path[, options], callback)

fs.readdirSync(path[, options])

- 读取一个目录的目录结构

- files 是一个字符串数组,每一个元素就是一个文件夹或文件的名字

fs.truncate(path[, len], callback)

fs.truncateSync(path[, len])

- 截断文件,将文件修改为指定的大小

fs.mkdir(path[, options], callback)

fs.mkdirSync(path[, options])

- 创建一个目录

fs.rmdir(path[, options], callback)

fs.rmdirSync(path[, options])

- 删除一个目录

fs.rename(oldPath, newPath, callback)

fs.renameSync(oldPath, newPath)

- 对文件进行重命名

- 参数

oldPath 旧的路径

newPath 新的路径

callback 回调函数

fs.watchFile(filename[, options], listener)

- 监视文件的修改

- 参数:

filename 要监视的文件的名字

options 配置选项

listener 回调函数,当文件发生变化时,回调函数会执行

在回调函数中会有两个参数

curr 当前文件的状态

prev 修改前文件的状态

这两个对象都是stats对象

7.10. 异步编程

7.10.1. 同步API, 异步API

同步API:只有当前API执行完成后,才能继续执行下一个API

console.log('before');

console.log('after');

异步API:当前API的执行不会阻塞后续代码的执行

console.log('before');

setTimeout(

() => { console.log('last');

}, 2000);

console.log('after');

7.10.2. 同步API, 异步API的区别( 获取返回值 )

同步API可以从返回值中拿到API执行的结果, 但是异步API是不可以的

// 同步

function sum (n1, n2) {

return n1 + n2;

}

const result = sum (10, 20);

// 异步

function getMsg () {

setTimeout(function () {

return { msg: 'Hello Node.js' }

}, 2000);

}

const msg = getMsg ();

7.10.3. 回调函数

自己定义函数让别人去调用。

// getData函数定义

function getData (callback) {}

// getData函数调用

getData (() => {});

使用回调函数获取异步API执行结果

function getMsg (callback) {

setTimeout(function () {

callback ({ msg: 'Hello Node.js' })

}, 2000);

}

getMsg (function (msg) {

console.log(msg);

});

7.10.4. 同步API, 异步API的区别(代码执行顺序)

同步API从上到下依次执行,前面代码会阻塞后面代码的执行

for (var i = 0; i < 100000; i++) {

console.log(i);

}

console.log('for循环后面的代码');

异步API不会等待API执行完成后再向下执行代码

console.log('代码开始执行');

setTimeout(() => { console.log('2秒后执行的代码')}, 2000);

setTimeout(() => { console.log('"0秒"后执行的代码')}, 0);

console.log('代码结束执行');

7.10.5. Node.js中的异步API

fs.readFile('./demo.txt', (err, result) => {});

var server = http.createServer();

server.on('request', (req, res) => {});

如果异步API后面代码的执行依赖当前异步API的执行结果,但实际上后续代码在执行的时候异步API还没有返回结果,这个问题要怎么解决呢?

fs.readFile('./demo.txt', (err, result) => {});

console.log('文件读取结果');

需求:依次读取A文件、B文件、C文件

7.10.6. Promise

Promise出现的目的是解决Node.js异步编程中回调地狱的问题。

let promise = new Promise((resolve, reject) => {

setTimeout(() => {

if (true) {

resolve({name: '张三'})

}else {

reject('失败了')

}

}, 2000);

});

promise.then(result => console.log(result); // {name: '张三'})

.catch(error => console.log(error); // 失败了)

7.10.7. 异步函数

异步函数是异步编程语法的终极解决方案,它可以让我们将异步代码写成同步的形式,让代码不再有回调函数嵌套,使代码变得清晰明了。

const fn = async () => {};

async function fn () {}

async关键字

普通函数定义前加async关键字 普通函数变成异步函数

异步函数默认返回promise对象

在异步函数内部使用return关键字进行结果返回 结果会被包裹的promise对象中 return关键字代替了resolve方法

在异步函数内部使用throw关键字抛出程序异常

调用异步函数再链式调用then方法获取异步函数执行结果

调用异步函数再链式调用catch方法获取异步函数执行的错误信息

await关键字

await关键字只能出现在异步函数中

await promise await后面只能写promise对象 写其他类型的API是不不可以的

await关键字可是暂停异步函数向下执行 直到promise返回结果

8 MongoDB数据库

8.1. 什么是数据库

数据库即存储数据的仓库,可以将数据进行有序的分门别类的存储。它是独立于语言之外的软件,可以通过API去操作它。

常见的数据库软件有:mysql、mongoDB、oracle、sqlserver。

8.2. MongoDB数据库下载安装

下载地址:https://www.mongodb.com/try/download/community

MongoDB可视化软件

下载地址:https://www.mongodb.com/try/download/compass

MongoDB数据库工具

下载地址:https://www.mongodb.com/try/download/database-tools

8.3. 数据库相关概念

在一个数据库软件中可以包含多个数据仓库,在每个数据仓库中可以包含多个数据集合,每个数据集合中可以包含多条文档(具体的数据)。

术语解释说明

database数据库,mongoDB数据库软件中可以建立多个数据库

collection集合,一组数据的集合,可以理解为JavaScript中的数组

document文档,一条具体的数据,可以理解为JavaScript中的对象

field字段,文档中的属性名称,可以理解为JavaScript中的对象属性

8.4. Mongoose第三方包

使用Node.js操作MongoDB数据库需要依赖Node.js第三方包mongoose

使用npm install mongoose命令下载

8.5. 启动MongoDB

在命令行工具中运行net start mongoDB即可启动MongoDB,否则MongoDB将无法连接。

8.5. 数据库连接

使用mongoose提供的connect方法即可连接数据库。

mongoose.connect('mongodb://localhost/playground',{ useNewUrlParser: true,useUnifiedTopology: true })

.then(() => console.log('数据库连接成功'))

.catch(err => console.log('数据库连接失败', err));

8.6. 创建数据库

在MongoDB中不需要显式创建数据库,如果正在使用的数据库不存在,MongoDB会自动创建。

8.7. MongoDB增删改查操作

8.7.1. 创建集合

创建集合分为两步,一是对集合设定规则,二是创建集合,通过mongoose.Schema构造函数的实例即可创建集合。

// 设定集合规则

const courseSchema = new mongoose.Schema({

name: String,

author: String,

isPublished: Boolean

});

// 创建集合并应用规则

const Course = mongoose.model('Course', courseSchema); // courses

8.7.2. 创建文档

创建文档实际上就是向集合中插入数据。

分为两步:

创建集合实例。

调用实例对象下的save方法将数据保存到数据库中。

// 创建集合实例

const course = new Course({

name: 'Node.js course',

author: '兵哥',

tags: ['node', 'backend'],

isPublished: true

});

// 将数据保存到数据库中

course.save(function(err,result){

// save方法,通过回调函数,返回添加的结果

if(!err){

console.log(result);

}

});

// 根据表对象,创建一个文档对象,并将该文档对象保存到数据库的数据表中(回调函数方式)

Course.create({name: 'JavaScript基础', author: '兵哥', isPublish: true}, (err, doc) => {

// 错误对象

console.log(err)

// 当前插入的文档

console.log(doc)

});

//根据表对象,创建一个文档对象,并将该文档对象保存到数据库的数据表中(Promise方式)

Course.create({name: 'JavaScript基础', author: '兵哥', isPublish: true})

.then(doc => console.log(doc))

.catch(err => console.log(err))

8.7.3. mongoDB数据库导入数据

mongoimport –d 数据库名称 –c 集合名称 –file 要导入的数据文件

找到mongodb数据库的安装目录,将安装目录下的bin目录放置在环境变量中。

8.7.4. 查询文档

// 根据条件查找文档(条件为空则查找所有文档)

Course.find().then(result => console.log(result))

// 返回文档集合

[{

_id: 5c0917ed37ec9b03c07cf95f,

name: 'node.js基础',

author: '兵哥'

},{

_id: 5c09dea28acfb814980ff827,

name: 'Javascript',

author: '兵哥'

}]

// 根据条件查找文档

Course.findOne({name: 'node.js基础'}).then(result => console.log(result))

// 返回文档

{

_id: 5c0917ed37ec9b03c07cf95f,

name: 'node.js基础',

author: '兵哥'

}

// 匹配大于 小于

// age:{$lt:30,$gt:18} 不包括18和30

// age:{$lte:30,$gte:18} 包括18和30

User.find({age: {$gt: 20, $lt: 50}}).then(result => console.log(result))

// $regex用于设置正则表达式搜索

// 通过select方法,限定查询哪些列,默认请情况_id都会返回,

// 如果不需要,通过-_id的方式去掉

User.find({name:{$regex:/刘/i}}).select('name sex age -_id').then(result=>{

console.log(result);

})

// 匹配包含

User.find({hobbies: {$in: ['敲代码','学习']}}).then(result => console.log(result))

User.find({hobbies: {$all: ['敲代码','学习']}}).then(result => console.log(result))

// 选择要查询的字段

User.find().select('name email').then(result => console.log(result))

// 将数据按照年龄进行排序

User.find().sort('age').then(result => console.log(result))

// 先根据性别升序,再根据年龄降序

User.find().sort('sex -age').then(result => console.log(result))

// skip 跳过多少条数据 limit 限制查询数量

User.find().skip(2).limit(2).then(result => console.log(result))

8.7.5. 删除文档

// 删除单个

Course.findOneAndDelete({}).then(result => console.log(result))

// 删除多个

User.deleteMany({}).then(result => console.log(result))

8.7.6. 更新文档

// 更新单个

User.updateOne({查询条件}, {要修改的值}).then(result => console.log(result))

// 更新多个

User.updateMany({查询条件}, {要更改的值}).then(result => console.log(result))

8.7.7. mongoose验证

在创建集合规则时,可以设置当前字段的验证规则,验证失败就输入插入失败。

required: true 必传字段

minlength:3 字符串最小长度

maxlength: 20 字符串最大长度

min: 2 数值最小为2

max: 100 数值最大为100

enum: ['html', 'css', 'javascript', 'node.js']

trim: true 去除字符串两边的空格

validate: 自定义验证器

default: 默认值

获取错误信息:error.errors['字段名称'].message

8.7.8. 集合关联

通常不同集合的数据之间是有关系的,例如文章信息和用户信息存储在不同集合中,但文章是某个用户发表的,要查询文章的所有信息包括发表用户,就需要用到集合关联。

使用id对集合进行关联

使用populate方法进行关联集合查询

// 用户集合

const User = mongoose.model('User', new mongoose.Schema({ name: { type: String } }));

// 文章集合

const Post = mongoose.model('Post', new mongoose.Schema({

title: { type: String },

// 使用ID将文章集合和作者集合进行关联

author: { type: mongoose.Schema.Types.ObjectId, ref: 'User' }

}));

//联合查询

Post.find()

.populate('author')

.then((err, result) => console.log(result));

9 Express框架

9.1. Express框架是什么

Express是一个基于Node平台的web应用开发框架,它提供了一系列的强大特性,帮助你创建各种Web应用。

我们可以使用 npm install express 命令进行下载。

Express框架特性:

提供了方便简洁的路由定义方式

对获取HTTP请求参数进行了简化处理

对模板引擎支持程度高,方便渲染动态HTML页面

提供了中间件机制有效控制HTTP请求

拥有大量第三方中间件对功能进行扩展

9.2. 路由

// 当客户端以get方式访问/时

app.get('/', (req, res) => {

// 对客户端做出响应

res.send('Hello Express');

});

// 当客户端以post方式访问/add路由时

app.post('/add', (req, res) => {

res.send('使用post方式请求了/add路由');

});

// 所有方式,优先级最高

app.all('/add',(req,res)=>{

res.send('使用get/post方式请求了/add路由');

})

9.3. 请求参数

app.get('/', (req, res) => {

// 获取GET参数

console.log(req.query);

});

app.post('/', (req, res) => {

// 获取POST参数

console.log(req.body);

})

9.4. Express初体验

使用Express框架创建web服务器及其简单,调用express模块返回的函数即可。

// 引入Express框架

const express = require('express');

// 使用框架创建web服务器

const app = express();

// 当客户端以get方式访问/路由时

app.get('/', (req, res) => {

// 对客户端做出响应 send方法会根据内容的类型自动设置请求头

res.send('Hello Express'); // <h2>Hello Express</h2> {say: 'hello'}

});

// 程序监听3000端口

app.listen(3000,()=>{console.log('服务已经启动,端口号3000')});

9.5. 中间件

9.5.1. 什么是中间件

中间件就是一堆方法,可以接收客户端发来的请求、可以对请求做出响应,也可以将请求继续交给下一个中间件继续处理。

中间件主要由两部分构成,中间件方法以及请求处理函数。

中间件方法由Express提供,负责拦截请求,请求处理函数由开发人员提供,负责处理请求。

app.get('请求路径', '处理函数') // 接收并处理get请求

app.post('请求路径', '处理函数') // 接收并处理post请求

可以针对同一个请求设置多个中间件,对同一个请求进行多次处理。

默认情况下,请求从上到下依次匹配中间件,一旦匹配成功,终止匹配。

可以调用next方法将请求的控制权交给下一个中间件,直到遇到结束请求的中间件。

app.get('/request', (req, res, next) => {

req.name = "张三";

next();

});

app.get('/request', (req, res) => {

res.send(req.name);

});

9.5.2. app.use中间件用法

app.use 匹配所有的请求方式,可以直接传入请求处理函数,代表接收所有的请求。

app.use((req, res, next) => {

console.log(req.url);

next();

});

app.use 第一个参数也可以传入请求地址,代表不论什么请求方式,只要是这个请求地址就接收这个请求。

app.use('/admin', (req, res, next) => {

console.log(req.url);

next();

});

9.5.3. 中间件应用

路由保护,客户端在访问需要登录的页面时,可以先使用中间件判断用户登录状态,用户如果未登录,则拦截请求,直接响应,禁止用户进入需要登录的页面。

网站维护公告,在所有路由的最上面定义接收所有请求的中间件,直接为客户端做出响应,网站正在维护中。

自定义404页面。

9.5.4. 错误处理中间件

在程序执行的过程中,不可避免的会出现一些无法预料的错误,比如文件读取失败,数据库连接失败。

错误处理中间件是一个集中处理错误的地方。

app.use((err, req, res, next) => {

res.status(500).send('服务器发生未知错误');

})

当程序出现错误时,调用next()方法,并且将错误信息通过参数的形式传递给next()方法,即可触发错误处理中间件。

app.get("/", (req, res, next) => {

fs.readFile("/file-does-not-exist", (err, data) => {

if (err) {

next(err);

}

});

});

9.5.5. 捕获错误

在node.js中,异步API的错误信息都是通过回调函数获取的,支持Promise对象的异步API发生错误可以通过catch方法捕获。

异步函数执行如果发生错误要如何捕获错误呢?

try catch 可以捕获异步函数以及其他同步代码在执行过程中发生的错误。

app.get("/", async (req, res, next) => {

try {

await User.find({name: '张三'})

}catch(ex) {

next(ex);

}

});

9.6. 构建模块化路由

const express = require('express')

// 创建路由对象

const home = express.Router();

// 将路由和请求路径进行匹配

app.use('/home', home);

// 在home路由下继续创建路由

home.get('/index', () => {

// /home/index

res.send('欢迎来到博客展示页面');

});

// home.js

const home = express.Router();

home.get('/index', () => {

res.send('欢迎来到博客展示页面');

});

module.exports = home;

// admin.js

const admin = express.Router();

admin.get('/index', () => {

res.send('欢迎来到博客管理页面');

});

module.exports = admin;

// app.js

const home = require('./route/home.js');

const admin = require('./route/admin.js');

app.use('/home', home);

app.use('/admin', admin);

9.7. 参数

9.7.1. GET参数的获取

Express框架中使用req.query即可获取GET参数,框架内部会将GET参数转换为对象并返回。

// 接收地址栏中问号后面的参数

// 例如: http://localhost:3000/?name=zhangsan&age=30

app.get('/', (req, res) => {

console.log(req.query); // {"name": "zhangsan", "age": "30"}

});

9.7.2. POST参数的获取

旧版本的Express中接收post请求参数需要借助第三方包 body-parser。

// 引入body-parser模块

const bodyParser = require('body-parser');

// 配置body-parser模块

// 设置允许接收json格式的数据

app.use(bodyParser.json());

// 设置允许接收urlencoded格式的数据

app.use(bodyParser.urlencoded({ extended: false }));

新版本的Express不需要借助第三方包 body-parser

// 设置允许接收json格式的数据

app.use(express.json())

// 设置允许接收urlencoded格式的数据

app.use(express.urlencoded({extended:false}))

// 接收请求

app.post('/add', (req, res) => {

// 接收请求参数

console.log(req.body);

})

9.7.3. Express路由参数

app.get('/find/:id', (req, res) => {

console.log(req.params); // {id: 123}

});

localhost:3000/find/123

9.8. 静态资源的处理

通过Express内置的express.static可以方便地托管静态文件,例如img、CSS、JavaScript 文件等。

app.use(express.static('public'));

现在,public 目录下面的文件就可以访问了。

http://localhost:3000/images/kitten.jpg

http://localhost:3000/css/style.css

http://localhost:3000/js/app.js

http://localhost:3000/images/bg.png

http://localhost:3000/hello.html

10 AJAX

10.1. HTTP

HTTP (hypertext transport protocol) 协议 [超文本传输协议],协议详细规定了浏览器和万维网之间相互通信的规则。

约定,规则。

10.1.1. 请求

重点是格式与参数

行 类型(GET POST) / URL / HTTP/1.1

头 Host: baidu.com

Cookie: name=汽车

Content-type: application/x-www-form-urlencoded

User-Agent: chrome 83

空行

体 username=admin&password=admin

10.1.2. 响应

行 HTTP/1.1 (200/404/403/401/500) OK

头 Content-type: text/html;charset=utf-8

Content-length: 2048

Content-encoding: gzip

空行

<html><head></head><body><h1>Ajax</h1></body></html>

10.2. 同源策略

同源策略:是浏览器的一种安全策略。

同源:协议、域名、端口号 必须完全相同。

违背同源策略就是跨域。

如何解决跨域:

JSONP:是一个非官方的跨域解决方案,纯粹凭借程序员的聪明才智开发出来的,只支持get请求。

JSONP 就是利用script标签的跨域能力来发送请求的。

比如:img link iframe script。

CORS:跨域资源共享。是官方的跨域解决方案。

新增了一组HTTP首部字段,允许服务器声明哪些源站通过浏览器有权限访问哪些资源。

//设置响应头 设置允许跨域

response.setHeader('Access-Control-Allow-Origin','*');

//响应头 *表示所有类型的头信息都可以接受

response.setHeader('Access-Control-Allow-Headers','*');

10.3. 原生AJAX

10.3.1. GET 请求

//1. 创建对象constxhr=newXMLHttpRequest();//2. 初始化 设置请求方法和URLxhr.open('GET','http://127.0.0.1:8000/server?a=100&b=200&c=300');//3. 发送xhr.send();//4. 事件绑定 处理服务端返回的结果// on  when  当....时候// readystate 是 xhr 对象中的属性,表示状态 0 1 2 3 4// 0 表示未初始化// 1 表示open方法已经调用完毕// 2 表示send方法已经调用完毕// 3 表示服务端返回了部分的结果// 4 表示服务端返回了所有结果// change  改变xhr.onreadystatechange=function(){//判断(服务端返回了所有结果)if(xhr.readyState===4){//判断响应状态码 200 404 403 401 500//2xx 成功if(xhr.status>=200&&xhr.status<300){//处理结果 行 头 空行 体//1. 响应行console.log(xhr.status);//状态码console.log(xhr.statusText);//状态字符串console.log(xhr.getAllResponseHeaders());//所有响应头console.log(xhr.response);//响应体//设置 result 的文本result.innerHTML=xhr.response}else{}}}

10.3.2. POST 请求

//1. 创建对象constxhr=newXMLHttpRequest();//2. 初始化 设置类型与 URLxhr.open('POST','http://127.0.0.1:8000/server')//设置请求头//Content-Type 是设置请求体内容的类型//application/x-www.form-urlencoded 是参数查询字符串的类型//application/json 是json格式类型xhr.setRequestHeader('Content-Type','application/x-www-form-urlencoded')//自定义头xhr.setRequestHeader('name','bing')//3. 发送xhr.send('a=100&b=200&c=300')// xhr.send('a:100&b:200&c:300')//4. 事件绑定xhr.onreadystatechange=function(){//对状态判断if(xhr.readyState===4){if(xhr.status>=200&&xhr.status<300){//处理服务端返回的结果result.innerHTML=xhr.response}}}

10.3.3. 响应 JSON

//发送请求constxhr=newXMLHttpRequest();//设置响应体数据的类型xhr.responseType='json';//初始化xhr.open('GET','http://127.0.0.1:8000/json-server');//发送xhr.send()//事件绑定xhr.onreadystatechange=function(){if(xhr.readyState===4){if(xhr.status>=200&&xhr.status<300){// result.innerHTML = xhr.response//手动对数据转换// let data = JSON.parse(xhr.response)// console.log(data);// result.innerHTML = data.name//自动转换-->设置响应体数据的类型// console.log(xhr.response);result.innerHTML=xhr.response.name}}}

10.3.4. IE缓存问题

constxhr=newXMLHttpRequest();// url添加时间戳xhr.open('GET','http://127.0.0.1:8000/ie?t='+Date.now());xhr.send();xhr.onreadystatechange=function(){if(xhr.readyState===4){if(xhr.status>=200&&xhr.status<300){result.innerHTML=xhr.response}}}

10.3.5. 请求超时与网络异常

constxhr=newXMLHttpRequest();//超时设置 2s 设置xhr.timeout=2000//超时回调xhr.ontimeout=function(){alert('网络异常,请稍后重试!')}//网络异常回调xhr.onerror=function(){alert('你的网络似乎出了一些问题!')}xhr.open('GET','http://127.0.0.1:8000/delay');xhr.send();xhr.onreadystatechange=function(){if(xhr.readyState===4){if(xhr.status>=200&&xhr.status<300){result.innerHTML=xhr.response}}}

10.3.6. 取消请求

letxhr=newXMLHttpRequest();xhr.open('GET','http://127.0.0.1:8000/delay');//发送请求xhr.send()//取消请求xhr.abort()

10.3.7. 重复发送请求问题

//判断标识变量if(isSending)x.abort();//如果正在发送,则取消该请求,创建一个新的请求x=newXMLHttpRequest();//修改 标识变量的值isSending=truex.open('GET','http://127.0.0.1:8000/delay');x.send()x.onreadystatechange=function(){if(x.readyState===4){//修改标识变量isSending=false}}

10.4. jQuery AJAX

<!-- crossorigin="anonymous" 跨语言的属性设置 将不会携带该域名下的cookie --><scriptcrossorigin="anonymous"src="https://cdn.bootcdn.net/ajax/libs/jquery/3.5.1/jquery.js"></script>

10.4.1. GET方式

// 第四个参数:设置json。表示响应体是json对象

// 第四个参数:不设置。默认响应体是字符串

$.get('http://127.0.0.1:8000/jquery-server',{a:100,b:200},function(data){console.log(data);},'json')

10.4.2. POST方式

$.post('http://127.0.0.1:8000/jquery-server',{a:100,b:200},function(data){console.log(data);})

10.4.3. 通用型方法ajax

$.ajax({//url        url:'http://127.0.0.1:8000/jquery-server',//参数data:{a:100,b:200},//请求类型type:'GET',//响应体结果dataType:'json',//成功的回调success:function(data){console.log(data);},//超时时间timeout:2000,//失败的回调error:function(){console.log('出错啦!');},//头信息headers:{c:300,d:400}})

10.5. axios

10.5.1. GET方式

axios.get('/axios-server',{//url 参数params:{id:100,vip:7},//请求头信息headers:{name:'bing',age:20}}).then(value=>{console.log(value);})

10.5.2. POST方式

axios.post('/axios-server',{//请求体{username:'admin',password:'admin'},{//url 参数params:{id:200,vip:9},//请求头参数headers:{height:180,weight:180}}).then(value=>{console.log(value);})

10.5.3. 通用方式

axios({//请求方法method:'POST',//urlurl:'/axios-server',//url参数params:{vip:10,level:30},//头信息headers:{a:100,b:200},//请求体参数data:{username:'admin',password:'admin'}}).then(response=>{console.log(response);//响应状态码console.log(response.status);//响应状态字符串console.log(response.statusText);//响应头信息console.log(response.headers);//响应体console.log(response.data);})

10.6. fetch

fetch('http://127.0.0.1:8000/fetch-server?vip=10',{//请求方法method:'POST',//请求头headers:{name:'bing'},//请求体body:'username=admin&password=admin'}).then(response=>{// console.log(response);// return response.text()returnresponse.json()}).then(response=>{console.log(response);})

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 194,761评论 5 460
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 81,953评论 2 371
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 141,998评论 0 320
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,248评论 1 263
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 61,130评论 4 356
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,145评论 1 272
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,550评论 3 381
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,236评论 0 253
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,510评论 1 291
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,601评论 2 310
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,376评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,247评论 3 313
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,613评论 3 299
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 28,911评论 0 17
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,191评论 1 250
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,532评论 2 342
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,739评论 2 335

推荐阅读更多精彩内容

  • 一、cmd终端常用命令 1、dir 显示目录里面的所有文件(包括文件夹和文件) 2、cd.. 回到上一级目录 3、...
    温木阅读 1,321评论 0 1
  • 一、cmd终端常用命令 1、dir 显示目录里面的所有文件(包括文件夹和文件) 2、cd.. 回到上一级目录 3、...
    一个想读书的人阅读 533评论 0 0
  • 1.运行一个nodejs文件, 如一个js文件中只含有console.log("hello world");的文件...
    不忘初心_9a16阅读 5,758评论 0 8
  • 一、Node快速体验 1、 Node介绍 (1) Node.js是什么 Node 是一个基于Chrome V8 ...
    宠辱不惊丶岁月静好阅读 3,264评论 0 6
  • 前端工程化 前端工程化就是通过各种工具和技术,提升前端开发效率的过程 Node.js Node.js是除了浏览器之...
    安掌门dear阅读 554评论 0 1