Node.js 模块化的操作,简单明了的代码帮助你明白后端的实现和前端之前的交互,及解决跨域等问题

32 篇文章 0 订阅
9 篇文章 0 订阅

在这里插入图片描述

Node.JS 模块化

1、require 导入模块

const http=require('http')


2、exports 导出模块

db={name:'jine',age:22}
module.exports=db

内置模块使用

1、导包

const fs=require('fs');

2、调用unlink删除文件方法
fs.unlink('./tmp/hello.txt',(err)=>{
    if(err) throw err;
    console.log('已成功删除 /tmmp/hello')
})

-----------------------------------------------------------------------------------------
文件读取操作,例如

const fs=require('fs')

fs.readFile('./etc/passwd.txt','utf-8',(err,data)=>{
    console.log(err);
    //err是一个错误对象,没有就返回一个null
    console.log(data);
})


-----------------------------------------------------------------------------------------
文件写操作(如果没有文件会创建一个,若有会覆盖掉),例如:
const fs=require('fs')
const data=`
 我是一段文本内容,啦啦啦啦啦啦啦啦啦啦啦~~~

`
fs.writeFile('./etc/content.txt',data,(err)=>{
    if(err==null){
        console.log("文件保存成功√")
    }else{
        console.log(err)
    }
})
获取文件或目录的路径
console.log(__dirname)
/*获取的是当前文件的所在目录的绝对路径 */
console.log(__filename)
/*获取的是当前文件的绝对路径*/ 
path 模块
为了避免少些斜杠而导致路径不对,可以引入path模块

const path=require('path')
const filePath=path.join(__dirname,'test','file.txt')
console.log(filePath)
/*
c:\Users\Jine\Desktop\my_code_space\jine\Daily code practice\07、03\test\file.txt
*/
http 模块
//使用内置模块http创建一个服务器

//1、导入http模块
const  http=require('http')

//2、创建一个服务器 (返回值代表当前服务器)
const server=http.createServer((request,response)=>{
    //3、设置返回给用户看的内容
    response.setHeader('Content-Type','text/html;charset=utf-8')
    /*setHeader 防止中文乱码,所以要设置响应头 */
    response.end("你好,世界~")
})

//4、开启服务器
server.listen(1024,()=>{
    console.log("服务器开启~")
})


/*开启服务器后,可以在本地浏览器中访问 127.0.0.1:1024 或  localhost:1024*/
静态资源服务器
//导入模块
const http=require("http")
const fs=require("fs")
const path=require('path')

//创建服务器
const server=http.createServer((request,response)=>{
    //设置返回用户内容

    //获取用户请求哪一个资源
    let userRq=request.url
    
    //获取用户读取的资源对应的路径
    const filePath=path.join(__dirname,'web',userRq)

    //读取用户请求的资源文件
    fs.readFile(filePath,(err,data)=>{
        if(err==null){
            response.end(data)
        }else{
            response.end("404 not found")
        }
    })

    
})

server.listen(8888,()=>{
    console.log("服务器开启成功√")
})
URL 模块 (get)
"get 应用(数据存在url中,相对较小,req.url可以拿到)"
"get 安全性低,一般用于请求数据/获取数据

例如:

//导入模块
const http=require('http')
const url=require('url')

//创建服务器
const server=http.createServer((request,response)=>{
    /*通过request.url拿到前端传递过来的参数
     * 导入url模块,处理接受到的字符串
     * 调用parse方法,(参数1:要处理的url,参数2:如果写true便返回一个对象)
     * 返回的对象中有query属性,其也是一个对象,这个属性里面有get传递过来的参数
     */
    let URL=url.parse(request.url,true)
    // console.log(URL.query)
    response.end(JSON.stringify(URL.query))
    /*若拿到了get信息对应的数据,便可返回字符串给前端 */
})

//启动服务器
server.listen(8888,()=>{
    console.log("服务器已开启√")
})

querystring 模块(post)
"post 应用(数据存在请求体中,相对而言较大,传递到node.js会分小块传送)"
"post 一般用于提交数据"
"测试post接口软件 https://www.postman.com/downloads/"

node.js如何接收:
他也是一小块一小块的接收.
1.首先有一个容器
2.给req对象一个data事件(这个事件会执行很多次)这个事件里面就把这些小块的数据拼接起来
3.给req对象一个end事件(这个事件只会执行一次)表示数据传递完了
4.处理传递过来的数据转为对象 queryString.parse();


例如:

//导入模块
const http=require('http')
const querystring=require('querystring')
//创建服务器
const server=http.createServer((request,response)=>{
    //容器
    let postData=""

    //给request对象一个data事件

    //事件处理程序,chunk参数是这次传递过来的一小块内容
    request.on('data',(chunk)=>{
        //将每此传过来小块的内容放到容器中
        postData+=chunk
    })

    //数据传递完毕执行
    request.on('end',()=>{
        //打印容器
        console.log(postData)

        //解析容器中的数据,转为对象
        let postObj=querystring.parse(postData)
        console.log(postObj)
    })

    //可以根据post传来的参数,去数据库中判断是否正确
    //最后返回前端页面
    response.end("over")
})

//启动服务器
server.listen(8888,()=>{
    console.log("服务器已开启√")
})

第三方模块

爬虫模块
1、新建文件夹,文件夹名字非中文,且不要和模块名一样
2、在cmd打开这个文件夹,然后输入 npm init -y (初始化)
3、去npm官网,搜索crawler
4、在cmd中运行 npm i crawler(下载爬虫模块)
5、使用爬虫,如下代码


爬取元素内容,例如:
var Crawler = require("crawler");
 
var c = new Crawler({
    maxConnections : 10,
    // This will be called for each crawled page
    callback : function (error, res, done) {
        if(error){
            console.log(error);
        }else{
            var $ = res.$;
            // $ is Cheerio by default
            //a lean implementation of core jQuery designed specifically for the server
            console.log($("title").text());
        }
        done();
    }
});
 
// Queue just one URL, with default callback
c.queue('http://www.baidu.com');

-----------------------------------------------------------------------------------------
爬取图片或视频,例如:
var Crawler = require("crawler");
var fs = require('fs');
 
var c = new Crawler({
    encoding:null,
    jQuery:false,// set false to suppress warning message.
    callback:function(err, res, done){
        if(err){
            console.error(err.stack);
        }else{
            fs.createWriteStream(res.options.filename).write(res.body);
        }
        
        done();
    }
});
 
c.queue({
    uri:"https://image.baidu.com/search/detail?ct=503316480&z=0&ipn=false&word=%E7%BE%8E%E5%A5%B3&step_word=&hs=0&pn=7&spn=0&di=35090&pi=0&rn=1&tn=baiduimagedetail&is=0%2C0&istype=0&ie=utf-8&oe=utf-8&in=&cl=2&lm=-1&st=undefined&cs=3186997546%2C1762170182&os=86097226%2C93959096&simid=3448572432%2C288122016&adpicid=0&lpn=0&ln=3390&fr=&fmq=1593780721779_R&fm=&ic=undefined&s=undefined&hd=undefined&latest=undefined&copyright=undefined&se=&sme=&tab=0&width=undefined&height=undefined&face=undefined&ist=&jit=&cg=girl&bdtype=0&oriquery=&objurl=http%3A%2F%2Fb-ssl.duitang.com%2Fuploads%2Fitem%2F201309%2F03%2F20130903141830_Q4Wuc.jpeg&fromurl=ippr_z2C%24qAzdH3FAzdH3F4_z%26e3B17tpwg2_z%26e3Bv54AzdH3Frj5rsjAzdH3F4ks52AzdH3F8bnmndnllAzdH3F1jpwtsAzdH3F&gsm=7&rpstart=0&rpnum=0&islist=&querylist=&force=undefined",
    filename:"./mv.jpg",
    headers:{'User-Agent':'requests'}
    /*让服务器伪装成客户端,这样可以破解防爬虫 */
});
自动重启工具(nodemon)
在编写调试Node.js项目,修改代码后,需要频繁的手动close掉,然后再重新启动,非常繁琐。现在,我们可以使用nodemon这个工具,它的作用是监听代码文件的变动,当代码改变之后,自动重启。

例如:

nodemon app.js
package.json 和 package-lock.json
package.json
默认项目初始化json文件,用来描述项目的信息



1.使用npm5之前的版本,是不会生成package-lock json这个文件的。

2. npm5以后,包括npm5这个版本,才会生成package-lockjson文件

3.当使用npm安装包的时候,npm都会生成或者更新package-lock.json文件。

npm5以后的版本,在安装包的时候,不需要加--save (-S) 参数, 也会自动在package.json中保存依赖项(依赖包)。

当安装包的时候,会自动创建或者更新package-lock json文件。

package-lock.json文件内保存了node_ _modules中所有包的信息,包含这些包的名称、版本号、下载地址。

带来好处是,如果重新npm install的时候,就无需逐个分析包的依赖项,因此会大大加快安装速度。

从package-lock.json文件名来看,lock代表的是“锁定”的意思。

它用来锁定当前开发使用的版本号,防止npm instal的时候自动更新到了更新版本。

因为新版本有可能会更新老的api,导致之前的代码出错。

原来的package.json文件只能锁定大版本,也就是版本号的第一位,并不能锁定后面的小版本,你每次npm install
都是拉取的该大版本下的最新的版本,为了稳定性考虑我们几乎是不敢随意升级依赖包的,这将导致多出来很多工
作量,测试/适配等,所以package-lock.jison文件出来了,当你每次安装一个依赖的时候就锁定在你安装的这个版本
express 模块
1、安装前,先清空缓存,否则会报错。 (npm cache clean -f)
2、安装(npm i express)

使用如下,例如:

//导入模块
const express = require('express')

//调用express()方法创建服务器
const app = express()
 
//设置返回用户看的内容
app.get('/', function (req, res) {

//若用内置模块http创建的服务器,返回内容用res.end() 响应
//此express模块创建的服务器,用res.send() 响应
//使用express模块返回中文时不用给响应头中加中文转义,默认会转义
  res.send(`<h1>Hello World~</h1>
            <p>你好呀</p>
  `)
})

//开启服务器
app.listen(8888,()=>{
    console.log("服务器开启成功√")
})
创建静态资源服务器
访问express中文网的静态文件的创建(https://www.expressjs.com.cn/starter/static-files.html)

例如:

//导入模块
const express = require('express')

//调用express()方法创建服务器
const app = express()
 

//通过如下代码,便可将web目录下的图片、css文件、JavaScript文件对外开放访问
app.use(express.static('web'))

//开启服务器
app.listen(8888,()=>{
    console.log("服务器开启成功√")
})
实现简单的get 接口
/**
 * 接口:得到一条随机笑话
 * 接口地址:/joke
 * 请求方式:get 
 * 参数:无
 * 返回:一条笑话
 */

 //导包
 const express = require('express')


 //创建服务器
 const app = express()

 //写接口
 app.get('/joke',(req,res)=>{
    //实际开发是从数据库或其他数据源获取
    let arr=['世界是你的','程序员会找到女朋友','你的代码永不报错']
    let index=Math.floor(Math.random()*3); //0,1,2

    //返回笑话
    res.send(`<h1>${arr[index]}</h1>`)
 })

 //开启服务器
 app.listen(8888,()=>{
     console.log("服务器已开启√")
 })
实现带有参数的get接口
/**
 * 接口:查询英雄对应的外号
 * 接口地址:/name
 * 请求方式:get 
 * 参数:heroName
 * 返回:英雄外号
 */

 //导包
 const express = require('express')


 //创建服务器
 const app = express()

 //写接口
 app.get('/name',(req,res)=>{
    //要接受前端,传递过来的参数
    let hero=''
    //req.query返回的是一个对象
    //herName便是get请求的参数
    switch(req.query.heroName){
        case '提莫':
            hero='迅捷斥候'
            break;
        case '李青':
            hero="盲僧"
            break;
        case '阿狸':
            hero="九尾妖狐"
            break;
        case '猴子':
            hero="齐天大圣"
            break; 
        default:
            hero="该英雄查询不到"; 
            break;  
    }
    res.send(`<h1 style=color:red;>${hero}</h1>`)    
 })

 //开启服务器
 app.listen(8888,()=>{
     console.log("服务器已开启√")
 })
实现返回json数据的接口
/**
 * 接口:返回一个食物
 * 接口地址:/food
 * 请求方式:get
 * 请求参数:无
 * 返回值:json
 */

//导包
const express = require('express')


//创建服务器
const app = express()

//写接口
app.get('/food',(req,res)=>{
    //1、express模块写法:直接写成对象,这样会自动返回json格式
   res.send({
       foodName:'宫保鸡丁',
       price:22,
       description:'肉大,菜香,多吃不腻'
   })

//    //2、原生内置模块写法:使用内置模块setHeader设置
//    res.setHeader('Conten-Type','application/json');
//    res.send(`
//     foodName:'宫保鸡丁',
//     price:22,
//     description:'肉大,菜香,多吃不腻'
//     `)
})

//开启服务器
app.listen(8888,()=>{
    console.log("服务器已开启√")
})
实现简单的post 接口
/**
 * 接口:返回默认字符串
 * 接口地址:/str
 * 请求方式:post
 * 参数:无
 * 返回:这是一个post接口
 */

 //导包
 const express = require('express')


 //创建服务器
 const app = express()

 //写接口
 app.post('/str',(req,res)=>{
   
    res.send(`<h1>这是一个post接口</h1>`)
 })

 //开启服务器
 app.listen(8888,()=>{
     console.log("服务器已开启√")
 })
实现带有参数的post接口
导入第三方模块(npm i body-parser)


/**
 * 接口:用户登录
 * 接口地址:/login
 * 请求方式:post
 * 参数:username password
 * 返回:登录成功/登录失败
 */

//需要使用第三方模块body-parser获取post传递的过来的参数
//安装模块(npm i body-parser)

 //导包
 const express = require('express')
 const bodyParser=require('body-parser')


 //创建服务器
 const app = express()

 //parse application/ x-www-form-urlencoded
 //将post请求体中的格式转换为urlencoded格式
 app.use(bodyParser.urlencoded({extended:false}))

 //写接口
 app.post('/login',(req,res)=>{
    //实际开发根据数据库中的数据进行判断
    //req.body 返回的是post对象,username和password是自定义的参数
    if(req.body.username=='admin' && req.body.password=='88888888'){
        res.send({
            code:200,
            msg:"登录成功"
        })
    }else{
        res.send({
            code:400,
            msg:'账户密码不正确'
        })
    }
    
 })

 //开启服务器
 app.listen(8888,()=>{
     console.log("服务器已开启√")
 })
实现post方式传文本参数的接口
导入第三方模块(npm i multer)

/**
 * 接口:用户登录
 * 接口地址:/register
 * 请求方式:post
 * 参数:username password usericon(用户头像/图片文件)
 * 返回:注册成功/注册失败
 */

//需要使用第三方模块multer接受post传递过来的文本参数
//安装模块(npm i multerr)

 //导包
 const express = require('express')
 const multer=require('multer')
 
 //用包:创建一个uploads文件夹,接受传递来的文本
 let upload=multer({dest:'uploads/'})


 //创建服务器
 const app = express()


 //写接口
 app.post('/register',upload.single('usericon'),(req,res,next)=>{
    // req.file is the usericon file 
    //传过来的文件参数名用usericon
    // req. body will hold the text fields, if there were any
    //一起传过来的文件保存在req.body中

    //记录了传递过来的文件的一些信息
    console.log(req.file)
    
    //记录了传递过来的post对象和其中的参数
    console.log(req.body)

    
 })

 //开启服务器
 app.listen(8888,()=>{
     console.log("服务器已开启√")
 })
注册路由
后端路由
注册路由:说白了就是写接口(API)

将多个接口放入一个文件中,只开启一次服务器

例如:

//后端路由
//注册路由:说白了就是写接口(API)


//导包
const express = require('express')

//创建服务器
const app = express()

//注册路由

//1、注册接口
app.post('/register',(req,res)=>{
    //逻辑...
    res.send("注册成功")
})

//2、登录接口
app.post('/login',(req,res)=>{
    //逻辑...
    res.send("登录成功")
})

//3、获取所有英雄接口
app.get('/getAllHero',(req,res)=>{
    //逻辑...
    res.send("获取成功")
})

自定义模块

自定义模块(文件名为:'自定义模块.js'),如下:

let db={
    name:'jine',
    age:'22',
    fun(){
        console.log("我是一个方法")
    },
    funny(){
        console.log('我也是一个方法~~')
    }
}

//导出,提供接口
module.exports=db

-----------------------------------------------------
这样便可以使用我们自定义的模块如下:

//导包
const myMoudle=require('./自定义模块.js')

console.log(myMoudle.name)
console.log(myMoudle.age)
myMoudle.fun()
myMoudle.funny()

其他补充

服务器重定向

服务器主动修改浏览器地址栏

//导包
const express=require("express")

//创建服务器
const app=express()

//如果访问本服务器中找不到输入的这个页面,就会自动重定向跳转到指定页面
app.use((req,res)=>{
    //设置302响应头
    //结束响应
    res.writeHead(302,{
        Location:'https://blog.3xnb.com'
    });
    res.end("ok")
})


//启动服务器
app.listen(8888,()=>{
    console.log("服务器已开启√")
})

中间件

服务器开启之后和路由器响应之前执行的一个函数
这个函数可以操作req,res
next() 执行下一个中间件

例如:

//导包
const express=require("express")
const bodyParser=require("body-parser")


//创建服务器
const app=express()


//中间件
//服务器开启之后和路由器响应之前执行的一个函数
//这个函数可以操作req,res
//next() 执行下一个中间件
app.use((req,res,next)=>{
    console.log("LOGGED")
    
    next()
})

//API
app.get('/hello',(req,res)=>{
    res.end("Hello World~")
})



//启动服务器
app.listen(8888,()=>{
    console.log("服务器已开启√")
})

跨域

报错类型:'Access-Contril-Allow-Origin'

-----------------------------------------------------------------------------------------
什么是跨域?

浏览器使用ajax时,如果请求的接口地址和当前打开页面的地址不同源称之为跨域

同源:协议,地址,端口都相同(反之有一个不满足就为不同源)

-----------------------------------------------------------------------------------------
出于安全考虑,浏览器不允许,页面向不同源的接口请求数据,因为如果接口和网页不同源,浏览器默认认为是俩个不同的服务器。
解决跨域
跨域是前端工作中不可避免的问题:我们经常会出现请求不同源接口的情况,为了能够获取数据,解决跨域的问题方案也有很多,但是常用的就两种

■第一种: CORS(后端操作)
目前的主流方案,也是最简单的方案,直接让后端设置响应头,允许资源共享就ok.


跨域资源共享(CORS) 是一种机制,它使用额外的 HTTP 头来告诉浏览器  让运行在一个 origin (domain) 上的Web应用被准许访问来自不同源服务器上的指定的资源。当一个资源从与该资源本身所在的服务器不同的域、协议或端口请求一个资源时,资源会发起一个跨域 HTTP 请求。

例如:

app.get('/login',(req,res)=>{
    //设置响应头,允许资源被访问/共享
    res.setHeader('Access-Control-Allow-Origin','*')
    /*表示所有请求路径都可以请求这个接口*/
})


解决跨域问题,设置响应头的代码,可以在中间件中写,这样可以在所有接口中都会应用到(只在中间件写一次就可以了,不用再多个接口中去写,因为中间件是在服务器开启之后和路由响应之前执行的一个函数)

例如:

app.use((req,res,next)=>{
     //在中间件中设置响应头,允许资源被所有接口访问/共享
    res.setHeader('Access-Control-Allow-Origin','*')
    next()
})

-----------------------------------------------------------------------------------------
    
或者还可以安装第三方模块(npm i cors)

例如:

//导入包
const cors=require('cors')
//使用
app.use(cors());
/*直接使用这个模块,便可省略在中间件中写的解决跨域问题的代码*/
■第二种:JSONP(前后端配合)
曾经的跨域杀手,专治各种跨域问题。现在慢慢的淡出历史舞台
PS:面试官特别喜欢问这个,因为这个有一定的技术难度,也能体现一个人的实际开发经验
jsonp是前后端来配合使用的.
使用原理:通过动态创建script标签通过script标签的src请求没有跨域限制来获取资源


补充知识:
浏览器页面上使用ajax发请求,当前页面地址和ajax请求的地址不同源,才会有跨域限制
但script、img、link标签中的src属性发的请求都没有跨域限制


使用jsonp原理:
这样便可以用script标签中的src来操作,去访问后端地址的接口时,前后端规定好使用的get请求传入的参数名便可,这样也没有了跨域限制


-----------------------------------------------------------------------------------------
前端页面,例如:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>JSONP</title>
</head>
<body>
    <script>
        function print(obj){
            alert(obj.user)
            alert(obj.data)
        }
    </script>
    <!-- 前端页面:访问后端API,传入后端指定get参数,后端处理返回后,接受到返回的调用和实参对象来使用 -->
    <script src="http://127.0.0.1:8888/getAll?fun=print"></script>
</body>
</html>

-----------------------------------------------------------------------------------------
后端页面,例如:

//导包
const express=require("express")

//创建服务器
const app=express()

app.get('/getAll',(req,res)=>{
    //接受到前端传入的get参数,当作函数调用这个参数,并传入实参对象,最后返回前端
    res.send(`${req.query.fun}({"user":"我是jine","data":"成功调用√"})`)
})

//启用服务器
app.listen(8888,()=>{
    console.log("服务器成功启动√")
})


-----------------------------------------------------------------------------------------
    
或者还可以直接在Ajax请求时,加上 dataType:'jsonp'

例如:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>点击哟</title>
    <script src="https://jine.oss-cn-beijing.aliyuncs.com/API/jquery-3.5.0.js"></script>
    <script>
        $(()=>{
            let $btn= $('button')
            $btn.on("click",()=>{
                $.ajax({
                    url:'http://127.0.0.1:8888/getAll',
                    dataType:'jsonp',
                    success:(backData)=>{
                        alert(backData.user)
                        alert(backData.data)
                    }
                })

                // 如果访问的接口支持jsonp,那么发送ajax便可以使用jsonp
                //  ajax加 dataType:'jsonp' 便可使用
                //  加的原理是:自动创建一个script标签,用他的src属性去请求服务器

                //注意:后端中的参数必须是callback,因为使用ajax开启jsonp,src传递的参数是callback,所以要一致
            })
        })
    </script>
</head>
<body>
    <button>点击我哟~</button>
</body>
</html>

"注意:后端中的参数必须是callback,因为使用ajax开启jsonp,src传递的参数是callback,所以要一致"

聚合数据(API)

百度搜索聚合数据,进入官方
便可调用别人提供已经写好的API
只要使用的接口支持jsonp,那么可以用ajax去请求
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值