0、webstom2020解决node代码不自动提示及显示警告的bug
完美解决Webstorm不支持nodejs等语法提示和补全
https://blog.csdn.net/Dobility/article/details/87563057
1、最简单的node执行脚本
创建一个js文件
var foo="hello world"
console.log(foo)
直接在cmd中进行编译执行
node xxx.js
直接会输出foo的内容
2、fs.readFile关于读文件
node里没有文件操作,要向进行读文件操作就必须映入fs核心模块
格式
fs.readFile(“内容字符串”,回到函数)
var fs=require('fs')
成功:
文件写入成功:
data是数据
error是null
失败:
文件写入失败
data是undefined没有数据
error是错误对象
案例
var fs=require('fs')//导入fs模块用于读文件操作
fs.readFile('hello.txt',function(error,data){
console.log(data.toString())
})
改进:
var fs=require('fs')
fs.readFile('hellos.txt',function(error,data){
if(error){
console.log("读取文件失败")
}else{
console.log(data.toString())
}
})
3、fs.writeFile写文件
格式:
fs.writeFile(“写入文件url”,“写入内容”,回调函数)
-
成功:
文件写入成功:
error是null -
失败
文件写入失败
error就是错误对象
var fs=require('fs')
fs.writeFile("sayhello.txt","大家好,我是node.js",function(error){
console.log("文件写入成功")
})
改进
var fs=require('fs')
fs.writeFile("sayhello.txt","大家好,我是node.js",function(error){
if(error){
console.log("写入失败")
}else{
console.log("写入成功")
}
})
3.1、path模式拼接路径
根据服务器所使用的不同系统,拼接路径(斜杠方式不一样)
const fs= require('fs');
const path=require('path')
let newpath=path.join('e:','myproject')
console.log(newpath)
输出结果:
e:\myproject
3.2、path模式下通过__dirname获取路径
__dirname获得node当前目录
const fs= require('fs');
const path=require('path')
fs.readFile(path.join(__dirname,'b.js'),'utf8',(err,doc)=>{
console.log(err)
console.log(doc)
})
3.3、gulp 报异步错误
gulp时,node报node did you forget to signal async completion错误
使用ruturn 返回gulp
const gulp=require('gulp');
const htmlmin=require('gulp-htmlmin');
const fileinclude=require('gulp-file-include')
const less=require('gulp-less')
gulp.task('first',()=>{
console.log('人生中的第一个gulp任务');
return gulp.src('./src/css/base.css')
.pipe(gulp.dest('dist/css'));
});
gulp.task('htmlmin',()=>{
return gulp.src('./src/*.html')
.pipe(fileinclude())
//压缩html文件中的代码
.pipe(htmlmin({collapseWhitespace: true}))
.pipe(gulp.dest('dist'));
})
//less语法转换,css代码压缩
gulp.task('cssmin',()=>{
//选择css目录下的所有lss文件及css文件
return gulp.src(['./src/css/*.less','./scr/css/*.css'])
//将less语法转换为css语法
.pipe(less())
//将css代码进行压缩
.pipe(csso())
//将处理的结果进行输出
.pipe(gulp.dest('dist/css'))
})
4、node创建服务器
1、加载htpp核心模块
var myhttp=require('http');
2、使用http.createServer()创建一个web服务器,返回一个server实例
var server=myhttp.createServer();
3、服务器的作用
- 提供数据服务
- 发请求
- 接收请求
- 处理请求
- 给个反馈(发送响应)
- 注册request请求事件
- 当客户端请求过来,就会自动触发服务器的request请求事件,然后执行第二个参数(回调函数):
server.on('request', function (request,response) {
console.log('收到客户端的请求了,请求路径是:' + request.url)
response.write("hello")
response.write("nodjs")
response.end()
})
request请求事件处理函数,需要接受两个参数:
-
request请求对象
请求对象可以用来获取客户端的一些请求信息,例如请求路径request.url
-
reponse响应对象
响应对象可以向客户端发送响应消息
response有一个方法,write可以用来给客户端发送响应数据
write可以使用多次,但是最后一定要使用end来结束响应,否则客户端会一直等待
可以根据不同的请求路径响应不同的结果
- 获取请求路径
request.url获取到的是端口号之后的那一部分路径,也就是说所有的url都是以/开头的 - 判断处理路径响应
4、绑定端口路号启动服务器
server.listen(8848, function () {
console.log("服务器启动成功了,可以通过8848端口号进行访问")
})
ctrl+c结束掉服务器
完整代码:
var fs = require('fs')
var myhttp = require('http')
var server=myhttp.createServer();
server.on('request', function (request,response) {
console.log('收到客户端的请求了,请求路径是:' + request.url)
response.write("hello")
response.write("nodjs")
response.end()
//也可以是用如下简写方式
reponse.end("hello world")
})
server.listen(8848, function () {
console.log("服务器启动成功了,可以同过8848端口号进行访问")
})
根据不同的请求路径返回不同的返回结果,response的响应内容只能是二进制数据或者字符串,数字,对象,数组,布尔值
var fs = require('fs')
var myhttp = require('http')
var server=myhttp.createServer();
server.on('request', function (request,response) {
console.log('收到客户端的请求了,请求路径是:' + request.url)
if (request.url === "/products") {
var products = [
{
name: '苹果X',
price: 999,
},
{
name: '华为X',
price: 3399,
},
{
name: '小米',
price: 1999,
}
];
//console.log(products);
console.log(JSON.stringify(products));//数组转字符串
}
})
server.listen(8848, function () {
console.log("服务器启动成功了,可以同过8848端口号进行访问")
})
5、node核心模块
node为JavaScript提供给了很多服务器级别的API,这些API绝大多数都被包装到了一个具名的核心模块中了,例如:
- fs:文件操作模块
- http:http服务模块
- path:路径操作模块
- os:操作系统信息模块
这些核心模块的必须要引入才能使用,如
var fs=require('fs')
node中,模块有三种
- 具名的核心模块,例如fs,http
- 用户自己编写的文件模块,
相对路径必须加 ./
模块也就是一个js文件,使用require导入,可以省略后缀名
支持链式导入,a导入b,b导入c,最终等同于a导入c - 在node中,没有全局作用域,只有模块作用域
外部访问不到内部,内部也访问不到外部,默认都是封闭的
模块之间如何通信
require方法两个作用:
- 1、加载文件模块并执行里面的代码
- 2、拿到被加载文件模块到处的接口对象
在每个文件模块中都提供了一个默认对象:exports,默认是个空对象,把所有需要被外部访问的成员挂载到exports中
b.js文件
var foo='bbb'
exports.foo = 'hello'//添加了需要被外部访问的成员
exports.add = function (x, y) {
return x+y
}
console.log(exports)
ex001.js
var ret = require('./b')
console.log(ret)
console.log(ret.foo)
console.log(ret.add(10,50))
6、关于ip地址和端口号
- ip地址用来定位计算机
- 端口号对应具体应用软件
- 一切需要联网的软件都会占用一个端口号
- 端口号从0-65536之间
- 在计算机中有些默认的端口号
- 可以同时开启多个服务,但一定要确保不同服务占用的端口号不一致
7、设置编码格式
var fs = require('fs')
var myhttp = require('http')
var server=myhttp.createServer();
server.on('request', function (request, response) {
var url = request.url
if (url === '/plain') {
response.setHeader('Content-type', 'text/plain; charset=utf-8')
response.end("你好 中国")
} else if (url === '/html') {
response.setHeader('Content-type', 'text/html; charset=utf-8')
response.end('<h1>hello html标签</h1>')
}
})
server.listen(8848, function () {
console.log("服务器启动成功了,可以同过8848端口号进行访问")
})
Content-type资源类型:
- text/css
- text/plain
- text/html
- image/jpeg
- image/png
案例:
var fs = require('fs')
var myhttp = require('http')
var server=myhttp.createServer();
server.on('request', function (request, response) {
var url = request.url
if (url === '/') {
fs.readFile('index.html', function (err, data) {
if (err) {
response.setHeader('Content-type', 'text/plain; charset=utf-8')
response.end("文件读取失败")
} else {
//data默认是二进制数据,可以通过toString转为能够识别的字符串
//response.end支持两种数据类型,一种是二进制,一种是字符串,因此可以直接读取
response.setHeader('Content-type', 'text/html; charset=utf-8')
response.end(data)
}
})
} else if (url === '/girl') {
fs.readFile('./gril03.jpg', function (err, data) {
response.setHeader('Content-type', 'image/jpeg')
response.end(data)
})
}
})
server.listen(8848, function () {
console.log("服务器启动成功了,可以同过8848端口号进行访问")
})
8、读取get方式传递的参数
服务器端代码
// 用于创建网站服务器的模块
const http = require('http');
// 用于处理url地址
const url = require('url');
// app对象就是网站服务器对象
const app = http.createServer();
// 当客户端有请求来的时候
app.on('request', (req, res) => {
// 获取请求方式
// req.method
// console.log(req.method);
// 获取请求地址
// req.url
// console.log(req.url);
// 获取请求报文信息
// req.headers
// console.log(req.headers['accept']);
res.writeHead(200, {
'content-type': 'text/html;charset=utf8'
});
console.log(req.url);
// 1) 要解析的url地址
// 2) 将查询参数解析成对象形式
let { query, pathname } = url.parse(req.url, true);
console.log(query.name)
console.log(query.age)
if (pathname == '/index' || pathname == '/') {
res.end('<h2>欢迎来到首页</h2>');
}else if (pathname == '/list') {
res.end('welcome to listpage');
}else {
res.end('not found');
}
if (req.method == 'POST') {
res.end('post')
} else if (req.method == 'GET') {
res.end('get')
}
// res.end('<h2>hello user</h2>');
});
// 监听端口
app.listen(3000);
console.log('网站服务器启动成功');
9、读取post方式传递的参数
服务器端代码
// 用于创建网站服务器的模块
const http = require('http');
// app对象就是网站服务器对象
const app = http.createServer();
// 处理请求参数模块
const querystring = require('querystring');
// 当客户端有请求来的时候
app.on('request', (req, res) => {
// post参数是通过事件的方式接受的
// data 当请求参数传递的时候出发data事件
// end 当参数传递完成的时候出发end事件
let postParams = '';
req.on('data', params => {
postParams += params;
});
req.on('end', () => {
console.log(querystring.parse(postParams));
});
res.end('ok');
});
// 监听端口
app.listen(3000);
console.log('网站服务器启动成功');
10、路由
// 1.引入系统模块http
// 2.创建网站服务器
// 3.为网站服务器对象添加请求事件
// 4.实现路由功能
// 1.获取客户端的请求方式
// 2.获取客户端的请求地址
const http = require('http');
const url = require('url');
const app = http.createServer();
app.on('request', (req, res) => {
// 获取请求方式
const method = req.method.toLowerCase();
// 获取请求地址
const pathname = url.parse(req.url).pathname;
res.writeHead(200, {
'content-type': 'text/html;charset=utf8'
});
if (method == 'get') {
if (pathname == '/' || pathname == '/index') {
res.end('欢迎来到首页')
}else if (pathname == '/list') {
res.end('欢迎来到列表页')
}else {
res.end('您访问的页面不存在')
}
}else if (method == 'post') {
}
});
app.listen(3000);
console.log('服务器启动成功')
11、静态资源
const http = require('http');
const url = require('url');
const path = require('path');
const fs = require('fs');
const mime = require('mime');
const app = http.createServer();
app.on('request', (req, res) => {
// 获取用户的请求路径
let pathname = url.parse(req.url).pathname;
pathname = pathname == '/' ? '/default.html' : pathname;
// 将用户的请求路径转换为实际的服务器硬盘路径
let realPath = path.join(__dirname, 'public' + pathname);
let type = mime.getType(realPath)
// 读取文件
fs.readFile(realPath, (error, result) => {
// 如果文件读取失败
if (error != null) {
res.writeHead(404, {
'content-type': 'text/html;charset=utf8'
})
res.end('文件读取失败');
return;
}
res.writeHead(200, {
'content-type': type
})
res.end(result);
});
});
app.listen(3000);
console.log('服务器启动成功')
12、异步编程–回调函数
格式
function getData(callback){ }
函数调用
getData(()=>{ } )
可以通过回调函数拿到异步处理的结果
示例
function getData(callback){
callback('123')
}
getData(function(n){
console.log('callback is used')
console.log(n)
});
另一个例子
function getMsg(callback){
setTimeout(function () {
callback({
msg:'hello node.js'
})
},2000)
}
getMsg(function(data){
console.log(data)
});
12.5、promise破解回调地狱
promise出现的目的是解决node.js异步编程中回调地狱的问题。实际是一个语法上的改进
- 创建一个promise对象,在构造函数中设计回调
- 使用then方法调用回调函数
let promise=new Promise((resolve,reject)=>{
setTimeout(()=>{
if (true){
resolve({name:'zhagnsan'})
}else{
reject('失败了')
}
},2000)
})
promise.then(result=>console.log(result))//实际执行的是then里面传入的函数
.catch(error=>log(error))
另一个案例
const fs=require('fs')
let promise=new Promise((resolve,reject)=>{
fs.readFile('./callback.js','utf8',(error,resualt)=>{
if (error!=null){
reject(error)//失败,想reject处理函数返传递error信息
}else{
resolve(resualt)//成功向resolve处理函数传递resualt结果
}
})
})
promise.then((result)=>{
console.log(result)
})
.catch((err)=>{
console.log(err)
})
13、异步函数
异步函数是异步编程语法的终极解决方案,它可以让我们将异步代码写成同步的形式,让代码不再有回调函数嵌套,是代码变得清晰明了
- 在普通函数前加上async关键字就可以将普通函数变成异步函数。
- 异步函数默认的返回值是promise对象
- 在异步函数内部使用throw关键字进行错误的抛出
格式为:
const fn=async ()=>{
}
async function fn(){
}
具体案例
async function fn(){
return 123//使用return关键字替代了原有的resolve方法
}
fn().then(function (data) {
console.log(data)
})
async function fn(){
return 123//使用return关键字替代了原有的resolve方法
}
fn().then(function (data) {
console.log(data)
})
.catch(function(err){
console.log(err)
})
14、异步函数的await关键字
- 她只能出现在异步函数中
- await promise可以暂停异步函数的执行 等待promise对象的返回的结果后再向下执行。
async function p1(){
return 'p1'
}
async function p2(){
return 'p2'
}
async function p3(){
return 'p3'
}
async function run(){
let r1=await p1()//会等p1()执行完再来执行下面的函数
let r2=await p2()//会等p2()执行完再来执行下面的函数
let r3=await p3()
console.log(r1)
console.log(r2)
console.log(r3)
}
run()
结果:依次输出p1,p2,p3
15、promisify对异步模块的包装
const fs=require('fs')
const promisify=require('util').promisify;//引入一个promisify的方法
const readFile=promisify(fs.readFile)//将fs.readFile进行了包装,包装成了一个异步方法
async function run(){
let r1=await readFile('./callback.js','utf8')
let r2=await readFile('./bewrited.txt','utf8')
let r3=await readFile('./helloworld.js','utf8')
console.log(r1)
console.log(r2)
console.log(r3)
}
run()
结果:
依次输出三个文件的内容
16、服务器端使用art-template模板
const template=require('art-template')
let ret=template.render('hello {{name}}',{
name:'macon'
})
console.log(ret)
17、控制哪些资源可以被访问到
const http=require('http')
const fs=require('fs')
const template=require('art-template')
const server=http.createServer()
server.on('request',(req,res)=>{
let url=req.url
if (url==='/'){
fs.readFile('views/index.html',(err,data)=>{
if (err){
return res.end('404,can not find the resource')
}
res.end(data)
})
}else if(url.indexOf('/public')===0){//控制那些资源可以被访问
fs.readFile('.'+url,(err,data)=>{
if (err){
return res.end('404,没有找到需要请求的资源')
}
res.end(data)
})
}
})
server.listen('3000',()=>{
console.log('the service is start at port 3000')
})
18、模块的导出
- 使用exports.xxx=变量或方法的形式来导出想要导出的内容(变量或方法)
- 使用时使用let 模块名=require(文件名)来导入想要使用的内容(变量和方法)
- 通过模块名.变量或方法来使用这个模块的内容(变量或方法)
- 可以使用module.exports={对象属性列表}的形式形式一次性导出多个内容(对象属性列表中的内容,即变量或方法),
myout.js
let outer1='hello node'
let outer2=function(x,y){
return x+y
}
module.exports={
outer1,
outer2
}
myin.js
const outer=require('./myout')
console.log(outer.outer1)
console.log(outer.outer2(3,5))