git、axios、模块化导出引入、promise、webpack、

news2024/11/27 9:35:39

GIT总结

在这里插入图片描述
git config --global user.name "你的用户名"
git config --global user.email "你的邮箱"
git config -l 命令来查看配置信息
git init 仓库初始化
touch index.html 创建index.html文件
git add index.html 文件加入暂存区
git add -A 将全部文件加入暂存区
git commit -m '注释' 文件提交到本地仓库
ls 查看文件夹下的文件
git ls-file暂存区中的文件列表
clearctrl + l 清屏
mkdir 创建文件夹
rm test.html 删除工作区中的文件
git rm --cache 文件名 删除暂存区中的文件
git rm -f 文件名 同时删除暂存区和工作区中的文件
git rm 文件夹1 文件夹2 -r --cache 删除暂存区中的文件夹
git rm -r -f 文件夹名(git rm -f -r 文件夹名)同时删除暂存区和工作区中的文件夹:
cat test.html 查看文件内容
git status 版本状态查看
git log --查看提交日志
git log --oneline 以一行简化的方式查看
git reset --hard 版本号 进行版本回退
git branch name 创建分支
git checkout name 切换分支
git merge name1 name2 合并分支
git branch -d name1 name2 删除分支
git checkout -b name 创建并切换分支
git clone 克隆远程仓库
git remote add 别名 远程仓库地址 本地配置远程仓库的地址,并将本地仓库内容推送到远程仓库
git push -u 别名 分支名(默认是master)-u 关联(长链接), 加上以后,后续提交时可以直接使用 git push
git remote remove 别名 别名可以添加,也可以删除
git remote 该命令是查看远程仓库别名
git push :将本地仓库的 某个分支 推送到远端仓库的 某个分支
git pull 拉取代码

配置忽略文件
Git中需要创建一个文件【.gitignore】配置忽略

git分段拉取代码
git config core.sparsecheckout true
echo ‘day19’ >>.git/info/sparse-checkout
git pull origin master
在这里插入图片描述

Axios

1.ajax请求的请求体数据格式

  • 当请求体数据为字符串时

    post请求体数据格式字符串:参数名=参数值&参数名=参数值…
    需要设置请求头
    xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
    建立一个请求体格式的字符串
    let str = "user=admin&pass=123456" ;
    发送请求体数据
    xhr.send(str)

    服务端需要设置字符串请求头解析

    解析请求体数据格式
    这句话解析的请求体格式:参数名=参数值&参数名=参数值
    解析的请求头:application/x-www-form-urlencoded
    app.use(bodyParser.urlencoded({ extended: false }));

  • 当请求体数据为对象时

post请求数据格式字符串:也可以是JSON类型的字符串 ‘{“user”:“admin”,“pass”:“123456”}’
对应JSON类型格式数据的请求头:application/json
xhr.setRequestHeader('Content-Type', 'application/json');
这个JSON对象的键名就是将来服务端要获取的请求体对象中的键名
let obj = { user:admin , pass:123456 }
将JSON对象转换成JSON字符串
let str = JSON.stringify(obj);
将JSON字符串放到send中作为请求体数据
xhr.send(str);

服务端需要设置JSON字符串请求头解析

这句话解析的请求体格式:‘{“user”:“admin”,“pass”:“123456”}’ JSON类型的字符串
解析的请求头:application/json
app.use(bodyParser.json())

2.axios

2.1.axios基本使用

get

axios({
      //配置对象

       //1、请求方式
       method: 'get',

       //2、请求url
       url: "http://bj0313.com/getserver",

       //3、请求字符串
       params: {
           id: 1,
           user: 'admin'
       },

       //4、请求头
       headers: {
           x: 1,
           y: 2
       }
   }).then(value => {
       //value都包含
       /*  
       config:(axios中的配置对象--开发中需要的,咱们程序员用不到)
       data:响应体数据
       request:原生的ajax请求对象
       headers:响应头
       status:响应状态码
       statusText:响应状态文本字符串
       */
       console.log(value)
   })

post、put、patch、deletes

post、put、patch、deletes的方法参数都一致
data的传参方式不一样
data传参方式可以是对象也可以是字符串的方式
delete方法只能只用对象方法传入data,不能用字符串的方法

function post() {
      axios({
        method: 'post',
        url: "http://localhost:8080/login",
        params: {
          id: 12,
          name: '瑶瑶'
        },
        headers: {
          a: 1,
          b: 2
        },
        // data: {
        //   accont: '141546154',
        //   pwd: 123456
        // }
        data: `accont=141546154&pwd=123456`  //data传参方式可以是对象也可以是字符串的方式
      }).then(res => {
        console.log(res)
      })
    }

    function put() {
      axios({
        method: 'put',
        url: "http://localhost:8080/userput",
        params: {
          id: 12,
          name: '瑶瑶'
        },
        headers: {
          a: 1,
          b: 2
        },
        // data: {
        //   accont: '141546154',
        //   pwd: 123456
        // }
        data: `accont=141546154&pwd=123456`//data传参方式可以是对象也可以是字符串的方式
      }).then(res => {
        console.log(res)
      })
    }

    function patch() {
      axios({
        method: 'patch',
        url: "http://localhost:8080/userpatch",
        params: {
          id: 12,
          name: '瑶瑶'
        },
        headers: {
          a: 1,
          b: 2
        },
        // data: {
        //   accont: '141546154',
        //   pwd: 123456
        // }
        data: `accont=141546154&pwd=123456`//data传参方式可以是对象也可以是字符串的方式
      }).then(res => {
        console.log(res)
      })
    }
    function deletes() {
      axios({
        method: 'delete',
        url: "http://localhost:8080/userdelete",
        params: {
          id: 12,
          name: '瑶瑶'
        },
        headers: {
          a: 1,
          b: 2
        },
        data: {//delete方法只能只用对象方法传入data,不能用字符串的方法
          accont: '141546154',
          pwd: 123456
        }
        // data: `accont=141546154&pwd=123456`  不能使用
      }).then(res => {
        console.log(res)
      })
    }

2.2axios独立方法的使用

  • axios.get(url请求地址,请求体对象)

    url地址请求:string类型
    请求体对象:{params:{},headers:{}}

  • axios.post(url请求地址,请求体对象,配置对象)
  • axios.put(url请求地址,请求体对象,配置对象)
  • axios.patch(url请求地址,请求体对象,配置对象)

    url地址请求:string类型
    请求对象:{键名:键值…} 也可以是字符串的形式 “键名=键值&键名=键值” ,但是基本上都用对象的形式
    配置对象:{params:{},headers:{}}

  • axios.delete(url请求地址,配置对象)

    url地址请求:string类型
    配置对象:{params:{},headers:{},data:{键名:键值…}}

  // get 方法
    async function get() {
      let res = await axios.get('http://localhost:8080/user', {
        params: { id: 12, name: '瑶瑶' },
        headers: { a: 1, b: 2 },
      })
      console.log(res)
    }
    // post 方法
    async function post() {
      // let res = await axios.post('http://localhost:8080/login', `accont=141546154&pwd=123456`, {
      //   params: { id: 12, name: '瑶瑶' },
      //   headers: { a: 1, b: 2 },
      // })
      let res = await axios.post('http://localhost:8080/login', { accont: '141546154', pwd: 123456 }, {
        params: { id: 12, name: '瑶瑶' },
        headers: { a: 1, b: 2 },
      })
      console.log(res)
    }
    // put 方法
    async function put() {
      let res = await axios.put('http://localhost:8080/userput', `accont=141546154&pwd=123456`, {
        params: { id: 12, name: '瑶瑶' },
        headers: { a: 1, b: 2 },
      })
      console.log(res)
    }
    // patch 方法
    async function patch() {

      let res = await axios.patch('http://localhost:8080/userpatch', `accont=141546154&pwd=123456`, {
        params: { id: 12, name: '瑶瑶' },
        headers: { a: 1, b: 2 },
      })
      console.log(res)
    }
    // deletes 方法
    async function deletes() {
      let res = await axios.delete('http://localhost:8080/userdelete', {
        params: { id: 12, name: '瑶瑶' },
        headers: { a: 1, b: 2 },
        // data: `accont=141546154&pwd=123456`  
        data: { accont: '141546154', pwd: 123456 } //deletes 中的data只能是对象的形式传入 不能用字符串的形式
      })
      console.log(res)
    }

2.3axios的默认配置的使用

配置对象用来设定【请求的参数以及功能的设置】

/*
 * method:请求类型
 * url:请求的url
 * params:请求的url参数
 * headers:请求头
 * data:请求体设置
 * baseURL:设置url的公共部分
*/
//axios函数执行时,传入的对象就是[配置对象 ]
axios({
	配置对象
})
axios.get('/server',{配置对象});
axios.post('/server',{},{配置对象})
//axios的默认属性配置,一旦配置了基础url,则后续请求都无需再写,请求时会自动添加
axios.defaults.baseURL = "http://127.0.0.1";
axios.get('/server');
axios.get('/json-server');
axios.get('/settings');
//设置默认超时时间
axios.defaults.timeout = 3000;
//设置默认请求类型
axios.defaults.method = 'GET';

2.4 axios创建实例对象发送请求

//创建实例对象
let duanzi = axios.create({
	method:'GET',
	baseURL:"https://v0.yiketianqi.com",
	timeout:3000
});

//使用实例对象发送请求,使用方式与axios使用方式相同
duanzi({
    url:'/api?unescape=1&version=v61&appid=82294778&appsecret=4PKVFula&city=北京'
}).then(response=>{
    console.log(response);
});

2.5 axios拦截器使用

2.5.1 什么是拦截器

拦截器本质上其实就是一些函数,里面有两类拦截器,一个是请求拦截器;一个是响应拦截器。

请求拦截器的作用:对请求的内容以及参数做处理和检查。

响应拦截器的作用:对响应的内容进行预处理。

2.5.2 请求拦截器

axios.interceptors.request.use(config=>{
	console.log('请求拦截器成功');
	return config;
},error => {
	console.error('请求拦截器失败');
	return Promise.reject(error);
})

2.5.3 响应拦截器

axios.interceptors.response.use(response=>{
	console.log('响应拦截器成功');
	return config;
},error => {
	console.error('响应拦截器失败');
	return Promise.reject(error);
})
//发送请求
axios({
	method:'get',
	url:"http://127.0.0.1/server"
}).then(value=>{
	console.log(value);
},reason=>{
	console.error(reason);
})

拦截器可以设置多个,当请求拦截器有多个时则倒序执行;响应拦截器有多个时则正序执行;

axios.interceptors.request.use(config=>{
	console.log('请求拦截器成功-1');
	return config;
},error => {
	console.error('请求拦截器失败-1');
	return Promise.reject(error);
})

axios.interceptors.request.use(config=>{
	console.log('请求拦截器成功-2');
	return config;
},error => {
	console.error('请求拦截器失败-2');
	return Promise.reject(error);
})
axios.interceptors.response.use(response=>{
	console.log('响应拦截器成功-1');
	return config;
},error => {
	console.error('响应拦截器失败-1');
	return Promise.reject(error);
})

axios.interceptors.response.use(response=>{
	console.log('响应拦截器成功-2');
	return config;
},error => {
	console.error('响应拦截器失败-2');
	return Promise.reject(error);
})

2.6 axios取消请求

<body>
    <button>发送请求</button>
    <button>取消请求</button>
</body>
<script>
    //获取按钮对象
	let btns = document.querySelectorAll('button');
	//声明变量
	let cancel = null;
	//发生点击事件
	btns[0].onclick = function(){
        //如果在发送之前想要取消则需要判断
        /*
         * 如果cancel已经为一个函数,则取消上一次请求
         * if(cancel){
             cancel();
         }
        */
        axios({
            method:"GET"
            url:"http://127.0.0.1/delay-server",
            cancelToken:new axios.CancelToken(function(c){
            	cancel = c;
        	});
        }).then(response=>{
            console.log(response);
        },error=>{
            console.warn(error);
        })
    }
    
    btns[1].onclick = function(){
        //调用cancel函数
        cancel();
    }
</script>

服务端

app.all('/delay-server',(request,response)=>{
	//延时 
    setTimeout(()=>{
        response.send('Hello abc');
    },3000);
})

CommonJS、ES6总结

一、常用的模块化代码:CommonJS、ES6

二、CommonJS语法

2.1 暴露

  • 暴漏任意数据
    module.exports = 值;
  • 暴露多个数据
    module.exports.键名 = 值;
  • 使用exports的方式暴露
    exports.键名 = 值

2.1 导入

let test = require("文件路径")
  • 文件:require('./文件名') require('../文件名')

省略文件后缀基本上是.js/.json为后缀的文件,除了这两个必须将后缀写清楚
文件中路径的./和…/是文件和文件之间在目录的层级上的路径,而非终端中的路径

  • 文件夹:require('./文件夹名') require('../文件夹名')

需要在这个文件夹里面查找package.json里面main属性的文件名,默认是index.js
如果在这个目录中这个文件则执行运行;
如果没有,有其他名称的文件,路径将自动补全:
require(‘./文件夹名/文件名’) require(‘…/文件夹名/文件名’)

  • 模块名:内置模块、第三方模块

如果是第三方模块名在当前文件夹下的node_modules目录里面没有找到,则自动上上一个文件目录的node_modules查找

注意事项:

  • 如果没有添加文件后缀,会默认按照.js/.json后缀的方式引入文件,同时有js和json同名的文件,没有添加文件后缀 js文件权重高
  • 其他文件后缀名,会按照.js方式载入
  • 如果是文件夹则会默认加载该文件夹下的package.json文件中main属性对应的文件
  • 如果是内置模块或者是npm安装的模块,直接使用包名字即可
  • npm引入包时,如果当前文件夹下的node_modules没有,则会自动向上查找

三、ES6模块化语法

  • 3.1 暴露

    • 分别暴露:export 变量声明
      export let 变量 = 值;
    • 统一暴露:
      export {变量1,变量2...}
    • 默认暴露:
      export default 值;
      值的数据类型是所有的常用数据类型(number、string、boolean、array、object、funciton)
  • 3.2 导入

    1. 适合于(分别暴露和统一暴露)的导入形式有两种:
    • 通用形式的导入:import * as 别名 from '子模块文件路径'
      这里的*表示所有,as表示别名 from来自于哪一个目标文件
    • 解构形式的导入:import {} from '子模块文件路径'
      {}里面写什么是子模块中export后面的变量名
    1. 适合于默认暴露的导入形式有两种:
    • 通用形式的导入:import * as 别名 from '子模块文件路径'
    • 默认形式的导入:import 变量名 from '子模块文件路径'

    注意:常见的错误写法 export default let a = 10;

三、browserify的使用

  • 全局安装 npm i -g browserify
  • 执行命令 browserify 入口文件 -o ./dist/bundle.js
    列:browserify ./build/app.js -o ./dist/bundle.js
    打包出能让浏览器识别的js
  • 然后运行<script src="./dist/bundle.js"></script>

四、babel转化ES6代码并打包

注意:除了将ES6的语法转换之外,还会将ES6的模块化语法,转化为CommonJS模块化语法

  • 全局安装
npm i babel-cli -g browserify 
  • 局部安装

    注意:在项目的文件夹下安装

npm i babel-preset-es2015
  • 创建.babelrc文件

    这个文件是babel运行的配置文件

{
	"presets":[
		"es2015"  //将es6的代码转化成es5
	]
}
  • 使用 Babel 将 ES6 编译为 ES5 代码
babel ./src -d ./build

js/src打包入口文件路径
js/build 打包出口文件路径

  • 使用Browserify编译js上一步生成的js
browserify ./build/main.js -o ./dist/build.js

./build/main.js 入口文件路径
./dist/build.js 出口文件路径

  • test.html页面引入测试
  <script type="text/javascript" src="js/build/build.js"></script>

promise总结

一、JS中的错误处理 try…catch

语法固定 try…catch try 尝试的意思 catch 捕获
1. try catch捕获到错误之后, 后续代码可以继续执行
2. catch 可以将错误信息捕获到. error参数是一个错误对象, 有message(错误信息)和stack(错误跟踪,精准到行和列)两个属性,使用console.dir(error)打印输出查看
3. 抛出错误之后, 在 try 里面的报错的后续代码就不再执行
4. try 不能捕获语法错误(syntaxError). 其他三种类型错误可以捕获(typeError类型错误、RangeError范围错误、以及throw抛出错误).
5. 允许使用 throw 手动的抛出错误
6. throw可以抛出任意类型的数据

try {
   try中存入有可能会出现错误的代码(文件操作...、连接数据库....、操作数据库方法....、ajax请求...1、TypeError错误:
     let a = 10.4656;
     a = {}
     // 在try中如果有哪一句话发生了错误,则后面的语句将不再执行
     console.log(a.toFixed(2));
     //前面的语句发生了错误,则这句123是不会在控制台中输出
     // console.log(123);

     2、RangeError:范围错误
     //Array构造函数中的参数表示数组的预计长度,起始为0,不能为负数
     // let arr = new Array(-1);
     // console.log(arr);

     3、SyntaxError语法错误,catch是无法捕捉的!!!
     // if () {

     4throw抛出的错误,catch也是可以捕捉的,可以抛出任意类型错误

     // throw new Error('错误消息');
     // throw new TypeError('错误消息');
     //throw后面可以抛出任意的数据类型,只要抛出了catch中的错误对象都可以捕捉
     // throw 100;
     // throw "我是错误字符串";
     // throw true;
     // throw [1, 2, 3];

 } catch (e) {
     //catch方法需要传入一个参数,这个参数表示错误对象
     //错误对象也是对象,那么可以通过console.dir方法查看对象的结构
     //错误对象中包含了两个属性,一个是message(错误消息)另一个是stack(错误跟踪,精准到行和列)
     console.dir(e);
 }
 //try...catch后面的语句是可以正常运行的
        console.log('hello');

在这里插入图片描述

二、promise基本使用

Promise的用途主要是为了实现一些异步任务,当这些异步任务的结果还没有得出的时候,此时Promise对象的状态仍然为pending

  • 创建promise对象(pending状态)
    const p = new Promise(executor)

    1、Promise本质是一个构造函数(产生一个实例化对象)
    2、Promise这个构造函数中需要传入一个参数,语法规定,必须要传入的,需要传入一个回调函数(executor 执行器函数)
    3、Promise构造函数中的实际参数的回调函数中还需要传递两个参数,且这两个参数仍然为回调函数
    这两个回调函数名基本不会改变:resolve(当前的状态是成功的)、reject(当前的状态是失败的)
    4、Promise主要为了实现异步编程(定时器、fs模块(文件写入、读取、删除…)、ajax、数据库操作方法)中提供成功/失败的结果
    5、Promise实例化对象有三个状态:pending(等待中...)、fulfilled(成功的状态)、rejected(失败的状态)
    6、Promise是通过其实例化对象的三个不同的状态来控制异步编程功能
    7、executor执行器函数中的两个形式参数也是可选参数,可加可不加,
    什么情况会添加?当如果想要改变Promise实例化对象的状态的时候是需要添加的,默认情况下Promise实例化对象的状态为pending

执行器回调函数中的两个回调函数作用:(resolve,reject)=>{}

  • reject的作用就是把Promise的状态从pending置为rejected,将实参设置到这个属性PromiseResult中,这样在then中就能捕捉到reject的回调函数
  • resolve的作用就是把Promise的状态从pending置为resolved,将实参设置到这个属性PromiseResult中,这样在then中就能捕捉到resolve的回调函数
const p = new Promise((resolve,reject)=>{
	//在回调函数中启动异步任务
    setTimeout(()=>{
        if(成功){
            resolve(实参);
        }else{
            reject(实参);
        }
    },2000)
})
  • 实例对象调用Promise原型中的then方法来完成对结果的处理
p.then((value)=>{
	//成功
},(reason)=>{
	//失败
})

三、Promise的状态改变

  • pending变为fulfilled
  • pending变为rejected

说明:只有这2种,且一个promise对象只能改变一次状态,状态一经改变,不可逆转

​ 无论变为成功还是失败,都会有一个结果数据

​ 成功的结果数据一般称为value,失败的结果数据一般称为reason

四、Promise实例对象的两个属性

  • PromiseState

    此属性为promise对象的状态属性。

    • fulfilled:成功的状态
    • rejected:失败的状态
    • pending:初始化的状态

    【注】状态只能由pending->fulfilled 或者是 pending->rejected

  • PromiseResult

    此属性为promise对象的结果值(resolve以及reject函数的形参值)
    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-q8uod8Ow-1686052789729)(null)]

五、node中的promisify

  • promisify (只能在 NodeJS 环境中使用)
  • promisify 是 util 模块中的一个方法 util 是 nodeJS 的内置模块
  • 作用: 返回一个新的函数, 函数的是 promise 风格的.
const util = require('util');
const fs = require('fs');
//promisify这个方法中需要传入一个以回调函数中是错误对象为优先的方法名
const mineReadFile = util.promisify(fs.readFile);

mineReadFile('./resource/2.html').then(value => {
    console.log(value.toString());
}, reason => {
    console.log(reason);
});

六、then 方法

then:指定用于得到成功value的成功回调和用于得到失败reason的失败回调,Promise的实例化对象调用Promise原型属性身上的then方法也是有返回值的,返回一个新的Promise对象

  • 成功的状态:执行第一个回调函数
  • 失败的状态:执行第二个回调函数

then方法返回一个Promise对象,它的的返回状态值的判断:

1、如果返回的是非promise的任意值, 新promise变为fulfilled, PromiseResult返回的值 ,如果没有retuen 返回值 PromiseResultundefined
2、如果返回的是另一个新promise, 此promise的结果就会成为新promise的结果
(当下这个新的Promise对象的状态将决定于then方法返回的Promise对象的状态,结果值亦然)
3、如果抛出异常, 新promise变为rejected, reason为抛出的异常

const p = new Promise((resolve,reject)=>{
     resolve('ok');
});

let result = p.then(value=>{
	1throw '错误信息';// 1抛出异常 错误
	2return 100;  // 值可以是字符串、数字、boolean、null、undefined、数组、对象都变为PromiseResult的结果
	3return new Promise((resolve,reject) => {
         // resolve();
         // reject();
         // throw 404;
        result的结果 取决于  此时设置的不同的状态 ,不设置的话result为pending
      })
},reason=>{
	console.log(reason);
});

console.log(result);
1、抛出异常的结果: PromiseState为rejected   PromiseResult为抛出的错误信息
2、 非promise的任意值  结果 :PromiseState为fulfilled   PromiseResult为return返回的值
3、result的结果 取决于  此时设置的不同的状态 ,不设置的话result为pending

当then方法没有传递成功/失败的回调函数的时候,那么p2的这个对象的状态和结果值???
如果then在书写的时候没有明确体现出成功/失败的时候,程序将默认补全
如果p1的状态为fulfilled的时候,then方法将补全成功回调函数为:value=>value 状态为fulfilled p1的结果值就是p2的结果值

   let p1 = new Promise((resolve, reject) => {
        resolve('ok');
    })
  //  let p2 = p1.then();  会转变为以下形式
    let p2 = p1.then(value => value);
    console.log(p2);

如果p1的状态为rejected的时候,then方法将补全失败回调函数为:reason=>{throw reason} p1的状态和结果值和p2是一致的

    let p1 = new Promise((resolve, reject) => {
        reject('error');
    })
 //  let p2 = p1.then();  会转变为以下形式
    let p2 = p1.then(() => { }, reason => {
        throw reason;
    });
    console.log(p2);

七、Promise的链式调用

通过then方法来实现链式调用

const p = new Promise((resolve,reject)=>{
	//resolve('ok');
    reject('error');
});

p.then(value=>{
	console.log(value);
},reason=>{
	console.log(reason);//error 失败状态,进入失败的函数
}).then(value=>{
	console.log(value);//undefined  此时的值取决于上一个Promise对象的状态
},reason=>{
	console.log(reason);
})

将 then 方法 的Promise对象的返回状态值的判断弄通这个链式调用中的值就懂了

八、终止Promise链条

通过 return new Promise((resolve, reject) => {}); 返回一个pending状态的promise对象 这样后续的链式调用就不再执行

new Promise((resolve, reject) => {
    resolve(111);
}).then(value=>{
    console.log(value);
    console.log(222);
    //
    // return false;
    // throw '出错啦';
    //有且只有一种方式 返回一个pending状态的promise对象
    return new Promise((resolve, reject) => {});
}).then(value => {
    console.log(333);
}).then(value => {
    console.log(444);
}).catch(reason => {
    console.log(reason);
});

九、Promise对象下的API方法

9.1.catch方法

功能是可以单独用来指定失败的回调函数

	let p1 = new Promise((resolve, reject) => {
      reject('error')
    })
    p1.catch(reason => {
      console.log(reason); //error
    })

catch方法也可以和then方法连用
当如果then方法可以catch方法连用的时候,并且then里面也有失败的回调函数的时候,具体是否还会向下执行catch
取决于then方法返回的那个新的Promise实例化对象的状态是否是失败的,因为catch方法是专门用于指定失败状态的这么一个方法
如果是失败的,会执行catch,反之不会

	let p1 = new Promise((resolve, reject) => {
      reject('error')
    })
    p1.then(value => {
      console.log(value)
    }, reason => {//进入到失败的回调
      // console.log(reason)
      return new Promise((resolve, reject) => {
        reject('错误...')
      })
    }).catch(reason => {//通过返回值进入到catch
      console.log(reason); //错误...
    })

异常(错误)穿透
当如果有多个需要执行的成功时的回调函数,可以不需要每一次都写失败回调,可以统一最后利用catch
当如果promise对象的状态为reject的话,会一直向下穿透直到catch方法

let p1 = new Promise((resolve, reject) => {
    reject('error')
 })
p.then(value=>{
    console.log(value);
}).then(value=>{
    console.log(value);
}).catch(reason=>{
    console.log(reason);//error
})

catch的返回值的用法和then是一样的 catch方法返回一个Promise对象,它的的返回状态值和then()方法是一样的

	let p1 = new Promise((resolve, reject) => {
      reject('error')
    })
    let p2 = p1.catch(reason => {
      console.log(reason); //error
    })
    console.log(p2) //Promise对象

9.2 resolve方法

创建一个成功状态的Promise实例化对象

  • 情况1:当如果resolve方法传递的为非Promise实例化对象的时候,
    则p1这个对象的状态为fullfilled,结果值为resolve方法的实际参数值
   let p1 = Promise.resolve(100);
     console.log(p1);
  • 情况2:当resolve方法传递的是promise实例化对象的时候,
    p2的状态和结果值完全取决于resolve方法的参数中的promise对象的状态和结果值
   let p2 = Promise.resolve(new Promise((resolve, reject) => {
       resolve('success');
   }))
   console.log(p2) //fulfllted 状态  值为success

9.3reject方法

返回的结果始终为失败的Promise对象
Promise.reject(值) 无论值是什么类型 都将已错误的值返回

 let p1 = Promise.reject(100);
console.log(p1); //  Promise对象 失败状态  值为100

  //reject的结果值仍然是reject这个方法的实际参数值
  let p1 = Promise.reject(new Promise((resolve, reject) => {
    resolve('success');
  }));
  console.log(p1);//  Promise对象 失败状态  值为传递的参数这个新的promise  看下图输出

在这里插入图片描述

9.4 all方法

作用:针对于多个Promise的异步任务进行处理

接收的参数:参数类型是一个数组,数组里面放的是promise的实例化对象

返回值:promise对象,状态由promise数组中的对象状态决定

  • 若每个对象状态都为成功,则返回的promise对象状态为成功,

​ 成功的结果值为每个promise对象成功结过值组成的数组

  • 不论有几个失败状态的对象 若任意一个对象状态为失败,则返回的promise对象状态为失败,

​ 失败的结果值为发现的第一个失败的promise对象的结果值 (以最快返回的第一个失败)

最终的请求时间是所有请求中耗时最长的请求所用的时间

let p1 = new Promise((resolve, reject) => {
            resolve('ok');
})
let p2 = Promise.resolve('success');
let p3 = Promise.resolve('okk');
let result = Promise.all([p1, p2, p3])
console.log(result);

在这里插入图片描述

10.5 race方法

Promise.race() race 赛跑的意思

参数: promise 数组

返回结果: promise 对象

状态由『最先改变状态的 promise对象』决定

结果值由 『最先改变状态的 promise对象』决定

race方法是需要看哪一个Promise对象的状态已经不再是pending了,
不管是fulfilled还是rejected,只要修改了则修改的这个对象的状态和结果值直接就是arr的状态和结果值(最先出现结果的值就会输出)

let p1 = new Promise((resolve, reject) => {
            setTimeout(() => {
                resolve('ok');
            }, 2000)
});
let p2 = Promise.resolve('success');
let p3 = Promise.resolve('oh hou');
let result = Promise.race([p1, p2, p3]);
console.log(result);// 成功状态的  success  p1 有定时器所有慢 p2 先输出

10.6 Promise.allSettled()

allSettled方法
参数仍然为promise 数组数组
返回的也是一个Promise实例化对象,其中包括两个状态,一个是fulfilled,一个是rejected

Promise.allSettled()方法,用来确定要一组异步操作是否都结束了(不管成功或失败)。
状态是fulfillesd ,值是以对象的形式返回每一项的状态和值 组成的数组

所以,它的名字叫"Settled",包含了"fufilled"和"rejected"两种情况.

最终的请求时间是所有请求中耗时最长的请求所用的时间
在这里插入图片描述

<script>
    function ajax(url) {
    return new Promise((resolve, reject) => {
        let xhr = new XMLHttpRequest();
        xhr.open('get', url, true);
        xhr.send();
        xhr.onreadystatechange = function () {
            if (xhr.readyState === 4) {
                if (xhr.status >= 200 && xhr.status < 300) {
                    resolve(xhr.responseText);
                } else {
                    reject(xhr.responseText);
                }
            }
        }
    })

}
//类比Promise下的all方法和allSettled
// Promise.all([ajax('http://www.xiongmaoyouxuan.com/api/tabs'),
// ajax('https://m.maizuo.com/gateway?cityId=110100&k=4770248')
// ]).then(value => {
//     console.log(value)
// }).catch(error => {
//     console.log(error);
// })

Promise.allSettled([ajax('http://www.xiongmaoyouxuan.com/api/tabs'),
                    ajax('https://m.maizuo.com/gateway?cityId=110100&k=4770248')
                   ]).then(value => {
    // console.log(value)
    let successList = value.filter(item => item.status === 'fulfilled');
    console.log(successList)

    let errorList = value.filter(item => item.status === 'rejected');
    console.log(errorList)
}).catch(error => {
    console.log(error);
})
</script>

10.7 Promise.any()

参数还是数组,数组中的内容是Promise实例化对象
只要参数实例有一个变成fulfilled状态,包装实例就会变成fulfiilled状态;

如果所有参数实例都变成rejected,包装实例就会变成rejected状态。

Promise.any()跟Promise.race()方法很像,但是有一点不同,
就是Promise.any()不会因为某个Promise变成rejected状态而结束,
必须等到所有参数Promise变成rejected状态才会结束。

10.8 Promise.finally()

finally是在ES9(ES2018)中新增的一个特性:表示无论Promise对象变成fufilled还是rejected状态,最终都会被执行。

finally方法中的回调函数是不接受参数的,因为无论前面是fulfilled状态还是rejected状态, 它都是执行。

const p = new Promise((resolve, reject) => {
    // resolve('ok');
    reject('error');
});
p.then(res => {
    console.log(res);
}).catch(err => {
    console.log(err);
}).finally(() => {
    console.log('finally')
})

十、async和await

async/await 是ES7提出的基于Promise的解决异步的最终方案。

10.1 async函数

async是一个加在函数前的修饰符,被async定义的函数会默认返回一个Promise对象resolve的值。

因此对async函数可以直接then,返回值就是then方法传入的函数。

async函数的返回值是一个Promise对象,这个Promise对象的状态到底是成功还是失败,取决于return后面值的类型
如果值类型为基本数据类型/引用数据类型, 则返回的Promise对象的状态为成功
如果值类型为promise实例化对象的话,则状态和返回的这个对象的状态有关联,状态值也是一样的

// async基础语法
async function fun0(){
    console.log(1);
    return 1;
}
fun0().then(val=>{
    console.log(val) // 1,1
})

async function fun1(){
    console.log('Promise');
    return new Promise(function(resolve,reject){
        resolve('Promise')
    })
}
fun1().then(val => {
    console.log(val); // Promise Promise
}
//声明一个async函数
async function main() {
    console.log('async function');
    //情况1:返回非promise对象数据
    return 'hahaha';
    //情况2:返回是promise对象数据
    /* return new Promise((resolve, reject) => {
		// resolve('ok');
		reject('error');
	}) */
    //情况3:抛出异常
    // throw new Error('出错啦!!!');
}
let result = main().then(value => {
    console.log(value);
});
console.log(result);

10.2 await表达式

await 也是一个修饰符,只能放在async定义的函数内。可以理解为等待

await 修饰的如果是Promise对象,可以获取Promise成功状态的结果值,且取到值后语句才会往下执行;
如果不是Promise对象:把这个非promise的东西当做await表达式的结果。
await后面是Promise成功状态的结果值
await后面如果是一个失败的Promise对象,则结果值需要通过使用try…catch来捕获得到
注意事项

  • await必须写在async函数中,但是async函数中可以没有await
  • 如果await的promise失败了,就会抛出异常,需要通过try…catch捕获处理
async function fun(){
    let a = await 1;
    let b = await new Promise((resolve,reject)=>{
        setTimeout(function(){
            resolve('setTimeout')
        },3000)
    })
    let c = await function(){
        return 'function'
    }()
    console.log(a,b,c)
}
fun(); // 3秒后输出: 1 "setTimeout" "function"
function log(time){
    setTimeout(function(){
        console.log(time);
        return 1;
    },time)
}
async function fun(){
    let a = await log(1000);
    let b = await log(3000);
    let c = log(2000);
    console.log(a);
    console.log(1)
}
fun(); 
// 立即输出 undefined 1
// 1秒后输出 1000
// 2秒后输出 2000
// 3秒后输出 3000
async function main() {
    //1、如果await右侧为非promise类型数据
    var rs = await 10;
    var rs = await 1 + 1;
    var rs = await "非常6+7";

    //2、如果await右侧为promise成功类型数据
    var rs = await new Promise((resolve, reject) => {
        resolve('success');
    })

    //3、如果await右侧为promise失败类型数据,需要借助于try...catch捕获
    try {
        var rs = await new Promise((resolve, reject) => {
            reject('error');
        })
        } catch (e) {
            console.log(e);
        }
}
main();
// 使用async/await获取成功的结果

// 定义一个异步函数,3秒后才能获取到值(类似操作数据库)
function getSomeThing(){
    return new Promise((resolve,reject)=>{
        setTimeout(()=>{
            resolve('获取成功')
        },3000)
    })
}

async function test(){
    let a = await getSomeThing();
    console.log(a)
}
test(); // 3秒后输出:获取成功

十一、代码

ES5写法

(function (window) {
    // executor是执行器函数
    function Promise(executor) {
        //构造函数中的this一定是指向其实例化对象的
        // 定义实例属性state,初始值为pending
        this.PromiseState = 'pending';
        // 定义实例属性result,初始值为undefined
        this.PromiseResult = undefined;
        // 定义实例属性callbackFun,起始值为一个数组
        this.callbackFun = [];
        /* [
            {onResolved:function(){},onRejected:function(){}},
            {onResolved:function(){},onRejected:function(){}},
            {onResolved:function(){},onRejected:function(){}}
        ] */

        // 定义resolve函数
        const _resolve = value => {
            // 当状态已经被更改过,不允许再次更改
            if (this.PromiseState !== 'pending') return;
            //在修改状态之前需要考虑一件事,Promise实例化对象的状态是否仍然是pending 
            //如果不是pending了,不管是fulfilled还是rejected,就不会执行后面的代码
            // 将状态更改为成功(fulfilled)
            this.PromiseState = 'fulfilled';
            // 成功值为value
            this.PromiseResult = value;
            //运行执行器函数内部的异步代码
            // console.log(this.callbackFun)
            this.callbackFun.forEach(item => {
                item.onResolved();
            })
        }
        // 定义reject函数
        const _reject = reason => {
            // 当状态已经被更改过,不允许再次更改
            if (this.PromiseState !== 'pending') return;
            // 将状态更改为失败
            this.PromiseState = 'rejected';
            // 将result设置为reason
            this.PromiseResult = reason;
            this.callbackFun.forEach(item => {
                item.onRejected();
            })
        }
        try {
            executor(_resolve, _reject);
        } catch (err) {
            _reject(err);// 状态更改为失败,值为异常信息
        }



    }

    // Promise.prototype.then = function () { }


    //对象间的合并
    //第二个参数(源对象)向第一个参数(目标对象)合并
    //合并的时候,如果两个对象中有相同的属性,则后者会覆盖前者
    Object.assign(Promise.prototype, {
        // onResolved:成功回调
        // onRejected:失败回调

        then(onResolved, onRejected) {

            //判断当then方法里面没有传递两个实际参数的回调函数的时候,需要添加默认值
            //instanceof是判断一个值是否所属于某一个构造函数的实例化对象
            //补充成功回调函数
            if (!(onResolved instanceof Function)) {
                onResolved = value => value; // value=>{return value}
            }

            //补充失败回调函数
            if (!(onRejected instanceof Function)) {
                onRejected = reason => {
                    throw reason;
                };
            }

            return new Promise((resolve, reject) => {

                const _common = function (callback) {
                    setTimeout(() => {
                        try {
                            // value是成功回调的返回值
                            const value = callback(this.PromiseResult);
                            // 判断value是不是通过Promise实例化出来的(判断value是否为Promise实例)
                            if (value instanceof Promise) {
                                value.then(v => {
                                    resolve(v);
                                }, r => {
                                    reject(r);
                                });
                            }
                            else {
                                // 不是Promise实例,将返回的Promise状态设置为成功,值为value
                                resolve(value);
                            }
                        } catch (err) {
                            // 有异常,将返回Promise的状态更改为失败,值为err
                            reject(err);
                        }

                    })
                }
                // 状态成功调用onResolved

                //这两种状态的改变相当于是同步代码的直接改变
                // p1的状态为成功
                if (this.PromiseState === 'fulfilled') {
                    _common.call(this, onResolved);
                } else if (this.PromiseState === 'rejected') {
                    _common.call(this, onRejected);
                } else {
                    //当异步任务没有执行完毕的时候,此时Promise实例化对象的状态为pending
                    //但是在pending的期间最终结果到底是fulfilled还是rejected,都有可能
                    //可以在当前Promise实例化对象身上添加一个回调函数的属性,用来存储两个回调(成功的回调,失败的回调)
                    this.callbackFun.push({
                        onResolved: _common.bind(this, onResolved),
                        onRejected: _common.bind(this, onRejected)
                    })
                }
            })
        },
        catch(onRejected) {
            //既然catch方法和then方法做的功能是一致的,那么我们没必要将代码在复制粘贴一份,而选择直接调用then方法
            // console.log(onRejected);
            return this.then(undefined, onRejected);
        }
    })

    //Promise对象下的方法添加
    // console.dir(Promise);

    Promise.resolve = function (value) {
        return new Promise((resolve, reject) => {
            //判断value的类型到底是不是一个Promise对象
            if (value instanceof Promise) {
                // console.log('实例化对象', value);
                // value.then(v => {
                //     resolve(v);
                // }, r => {
                //     reject(r);
                // })

                //简写的形式
                value.then(resolve, reject);
            } else {
                resolve(value);
            }
        })
    }

    Promise.reject = function (value) {
        return new Promise((resolve, reject) => {
            //直接将Promise实例化对象状态更改成rejected
            reject(value);
        })
    }

    Promise.all = function (value) {
        // 定义一个变量,用来计数(计成功的Promise的数量,到时候和数组的数量做对比)
        let index = 0;
        //定义一个数组,数组用来装如果all方法里面都是成功的Promise对象的结果值
        //new Array(数字):表示预设数组长度
        let arr = new Array(value.length); // [??]

        return new Promise((resolve, reject) => {
            value.forEach((item, i) => {
                // console.log('数组的每一项:', item);
                // console.log('数组的下标:', i)
                item.then(v => {
                    //只要有一个成功的Promise实例化对象,就让计数器+1
                    index++;
                    arr[i] = v;
                    if (index === value.length) {
                        //只要计数器数值和all方法中的长度一致,则证明数组中每一个元素都是成功的Promise对象
                        resolve(arr);
                    }
                }, r => {
                    //只要有失败,状态将立即更改
                    reject(r);
                })
            })
        })

    }

    Promise.race = function (value) {
        return new Promise((resolve, reject) => {
            value.forEach(item => {
                //从数组中的第一个Promise对象开始循环,只要能够进入到then的回调函数之中,不管是哪一个回调函数
                //说明此时Promise对象的状态一定不为pending,所以不管是成功还是失败,直接修改状态
                item.then(v => {
                    resolve(v);
                }, reason => {
                    reject(reason)
                })
            })
        })
    }

    window.Promise = Promise;
})(window);

class写法

(function (window) {
    //声明类
    class Promise {

        constructor(executor) {
            //this指向的是Promise这个类的实例化对象
            this.PromiseState = 'pending';
            this.PromiseResult = undefined;
            //当执行器函数内部的代码为异步代码的时候
            this.callbackFun = [];

            // 定义resolve函数
            const _resolve = value => {
                // 当状态已经被更改过,不允许再次更改
                if (this.PromiseState !== 'pending') return;
                //在修改状态之前需要考虑一件事,Promise实例化对象的状态是否仍然是pending 
                //如果不是pending了,不管是fulfilled还是rejected,就不会执行后面的代码
                // 将状态更改为成功(fulfilled)
                this.PromiseState = 'fulfilled';
                // 成功值为value
                this.PromiseResult = value;
                this.callbackFun.forEach(item => {
                    item.onResolved();
                })
            }

            // 定义reject函数
            const _reject = reason => {
                // 当状态已经被更改过,不允许再次更改
                if (this.PromiseState !== 'pending') return;
                // 将状态更改为失败
                this.PromiseState = 'rejected';
                // 将result设置为reason
                this.PromiseResult = reason;
                this.callbackFun.forEach(item => {
                    item.onRejected();
                })
            }

            try {
                executor(_resolve, _reject);
            } catch (err) {
                _reject(err);// 状态更改为失败,值为异常信息
            }
        }

        then(onResolved, onRejected) {

            //判断当then方法里面没有传递两个实际参数的回调函数的时候,需要添加默认值
            //instanceof是判断一个值是否所属于某一个构造函数的实例化对象
            //补充成功回调函数
            if (!(onResolved instanceof Function)) {
                onResolved = value => value; // value=>{return value}
            }

            //补充失败回调函数
            if (!(onRejected instanceof Function)) {
                onRejected = reason => {
                    throw reason;
                };
            }

            return new Promise((resolve, reject) => {

                const _common = function (callback) {
                    setTimeout(() => {
                        try {
                            // value是成功回调的返回值
                            const value = callback(this.PromiseResult);
                            // 判断value是不是通过Promise实例化出来的(判断value是否为Promise实例)
                            if (value instanceof Promise) {
                                value.then(v => {
                                    resolve(v);
                                }, r => {
                                    reject(r);
                                });
                            }
                            else {
                                // 不是Promise实例,将返回的Promise状态设置为成功,值为value
                                resolve(value);
                            }
                        } catch (err) {
                            // 有异常,将返回Promise的状态更改为失败,值为err
                            reject(err);
                        }

                    })
                }
                // 状态成功调用onResolved

                //这两种状态的改变相当于是同步代码的直接改变
                // p1的状态为成功
                if (this.PromiseState === 'fulfilled') {
                    _common.call(this, onResolved);
                } else if (this.PromiseState === 'rejected') {
                    _common.call(this, onRejected);
                } else {
                    //当异步任务没有执行完毕的时候,此时Promise实例化对象的状态为pending
                    //但是在pending的期间最终结果到底是fulfilled还是rejected,都有可能
                    //可以在当前Promise实例化对象身上添加一个回调函数的属性,用来存储两个回调(成功的回调,失败的回调)
                    this.callbackFun.push({
                        onResolved: _common.bind(this, onResolved),
                        onRejected: _common.bind(this, onRejected)
                    })
                }
            })
        }

        catch(onRejected) {
            //既然catch方法和then方法做的功能是一致的,那么我们没必要将代码在复制粘贴一份,而选择直接调用then方法
            // console.log(onRejected);
            return this.then(undefined, onRejected);
        }

        static resolve = function (value) {
            return new Promise((resolve, reject) => {
                //判断value的类型到底是不是一个Promise对象
                if (value instanceof Promise) {
                    // console.log('实例化对象', value);
                    // value.then(v => {
                    //     resolve(v);
                    // }, r => {
                    //     reject(r);
                    // })

                    //简写的形式
                    value.then(resolve, reject);
                } else {
                    resolve(value);
                }
            })
        }

        static reject = function (value) {
            return new Promise((resolve, reject) => {
                //直接将Promise实例化对象状态更改成rejected
                reject(value);
            })
        }

        static all = function (value) {
            // 定义一个变量,用来计数(计成功的Promise的数量,到时候和数组的数量做对比)
            let index = 0;
            //定义一个数组,数组用来装如果all方法里面都是成功的Promise对象的结果值
            //new Array(数字):表示预设数组长度
            let arr = new Array(value.length); // [??]

            return new Promise((resolve, reject) => {
                value.forEach((item, i) => {
                    // console.log('数组的每一项:', item);
                    // console.log('数组的下标:', i)
                    item.then(v => {
                        //只要有一个成功的Promise实例化对象,就让计数器+1
                        index++;
                        arr[i] = v;
                        if (index === value.length) {
                            //只要计数器数值和all方法中的长度一致,则证明数组中每一个元素都是成功的Promise对象
                            resolve(arr);
                        }
                    }, r => {
                        //只要有失败,状态将立即更改
                        reject(r);
                    })
                })
            })

        }

        static race = function (value) {
            return new Promise((resolve, reject) => {
                value.forEach(item => {
                    //从数组中的第一个Promise对象开始循环,只要能够进入到then的回调函数之中,不管是哪一个回调函数
                    //说明此时Promise对象的状态一定不为pending,所以不管是成功还是失败,直接修改状态
                    item.then(v => {
                        resolve(v);
                    }, reason => {
                        reject(reason)
                    })
                })
            })
        }
    }
    window.Promise = Promise;
})(window)

webpack代码

webpak.prod.js

//导入模块
const path = require('path');

//导入安装的第三方的包

//单独抽离成独立的css文件
const miniCssExtractPlugin = require('mini-css-extract-plugin');

//css压缩的
const CssMinimizerPlugin = require("css-minimizer-webpack-plugin");

//html文件的打包
const htmlWebpackPlugin = require('html-webpack-plugin');

//eslint代码检查包
const eslintWebpackPlugin = require('eslint-webpack-plugin');


// console.log(path.resolve('E:\\BJ0313\\day20\\代码\\webpack\\demo1', './abc'));

//__dirname:表示当前文件在定义时期所在的绝对路径:E:\\BJ0313\\day20\\代码\\webpack\\demo1\\config
// console.log(path.resolve(__dirname, '../dist'));

//向外暴露一个对象
module.exports = {
    //webpack打包的时候有五大核心:
    /* 
     *  entry(打包入口文件地址)
     *  output(打包文件路径出口)
     *  mode(打包的模式)
     *  ----------------------
     *  前面的三个属性可以单独为以.js结尾的文件进行打包
     * 
     *  但是,如果文件结尾为.css/.less/.png/.jpg/.gif/.mp4/.woff....等等这些后缀
     *  则需要模块以及插件来支持
     *  module(加载器)  
     *  plugins(插件)
     */

    //这个对象中的五个属性书写没有任何的顺序,但是一般情况下先从入口、出口、模块、插件、模式等这种顺序

    //打包的入口文件地址是针对于运行终端来说,而非这个webpack.prod.js和src目录之间的关系!!!!
    entry: './src/js/app.js',
    //打包的出口
    output: {
        //打包后的文件夹路径
        //path属性是语法,不能修改,后面的值是一个绝对路径
        //E:\BJ0313\day20\代码\webpack\demo1\dist
        //自动产生一个路径,需要借助于node中的内置模块:path
        path: path.resolve(__dirname, '../dist'),
        filename: 'js/bundle.js',
        //每一次重新打包的时候都会将上一次的结果清除掉
        clean: true,
         //公共路径
        publicPath: '/'
    },
    //打包模式
    mode: 'production',

    //加载器(loader)
    module: {
        //rules规则,这个rules后面是一个数组,里面存入的是对象形式的值,也就是说,有一个规则就配置一个对象
        rules: [
            //.css后缀的规则,那么就定义一个对象
            {
                //test是正则中的检测,后面的值写的是正则的规则
                //其中[.]和\.的含义等同,目的都是为了将.这个字符转化成普通的字符.
                //因为.在正则表达式中表示除了换行符以外的任意单个字符,保证用户在创建文件名的时候一定是xxx.css
                test: /[.]css$/i,
                //use后面到底是数组还是字符串,取决于使用的时候是一个加载器还是多个加载器
                //如果是多个加载器的话,那么需要写成数组
                //反之如果是一个加载器,则可以直接定义成字符串
                //并且如果是数组的话,则数组的执行顺序是由右->左
                //css-loader的作用主要是加载.css结尾的文件,并解析执行里面你的css语法,返回css语句
                //style-loader的作用主要是在index.html的head标签里面添加一个style标签存入css语法
                //也就是说,src/css文件夹里面有一个css文件,就把这个文件里面的语句在style标签中写一遍
                //考虑到文件的数量和文件中内容的数量,这种形式不是很合适
                // use: ['style-loader', 'css-loader']

                //如果css代码偏多,文件偏多,最终会使得index.html文件内容偏多
                //所以需要一个单独的插件包将所有开发时使用的css文件的内容抽离出来成一个单独的新的css文件
                //这样的话就需要一个插件包:miniCssExtractPlugin
                use: [miniCssExtractPlugin.loader, 'css-loader', {
                    loader: 'postcss-loader',
                    options: {
                        postcssOptions: {
                            plugins: [
                                [
                                    'postcss-preset-env'
                                ],
                            ],
                        },
                    },
                }]
            },
            {
                test: /\.less$/i,
                //顺序:由右->左
                use: ['style-loader', 'css-loader', 'less-loader']
            },
            {
                test: /\.(gif|png|jpe?g|webp)$/i,
                //如果某一个文件的后缀需要使用加载器,则是use配置属性, 如果是图片则直接是type类型
                type: 'asset',
                //默认是小于8KB会自动转化成base64,大于8KB的图片会参与打包,保存在dist目录中
                //如果想要修改这种默认的图片大小,需要单独设置parser这个属性
                parser:
                {
                    dataUrlCondition: {
                        maxSize: 10 * 1024 // 小于10kb的图片会被base64处理,则不会打包进dist文件夹,这样就可以减少针对于图片的请求,也降低了图片保存在目录中的占位
                    }
                },
                generator: {
                    // 将图片文件输出到 static/imgs 目录中
                    // 将图片文件命名 [hash:8][ext][query]
                    // [hash:8]: hash值取8位,可自定义,写几文件名就是几位的
                    // [ext]: 使用之前的文件扩展名
                    // [query]: 添加之前的query参数
                    //这个文件的路径是根据之前output中path里面的../dist目录判断的,相当于在dist目录下做配置
                    filename: "static/imgs/[hash:8][ext][query]",
                }
            },
            {
                test: /\.(ttf|woff2?|mp4|avi|wmv)$/,
                type: "asset/resource",  //相当于执行了file-loader 将字体文件输出到dist打包目录中
                generator: {
                    filename: "static/media/[hash:10][ext]",
                }
            },
            {
                test: /\.js$/,
                exclude: /node_modules/, // 排除node_modules代码不编译
                loader: "babel-loader",
            },
             {
                //检测以.ejs结尾的文件
                test: /\.ejs$/,
                //使用ejs-loader加载器来检测
                loader: 'ejs-loader',
                //配置项
                options: {
                    //ejs模板页面中的变量名
                    //可以自定义
                    variable: 'data'
                }
            },
        ]
    },
    //插件
    plugins: [
        new miniCssExtractPlugin({
            //抽离的独立css文件名
            //filename中的路径和文件名都可以自定义
            filename: 'static/css/main.css'
        }),
        new CssMinimizerPlugin(),
        new htmlWebpackPlugin({
            //需要打包的文件路径是什么???
            template: path.resolve(__dirname, '../public/index.html'),
            //打包后的文件叫什么???
            filename: 'index.html',
            //是否将打包的bundle.js文件自动添加到打包的html文件里面,如果是,放在哪里???
            inject: 'body'
        }),
        new eslintWebpackPlugin({
            context: path.resolve(__dirname, '../src'),
        })
    ],
    //源代码和构建后的代码需要产生一个映射关系
    devtool: 'source-map'
}

webpak.dev.js

//导入
const ProdConfig = require('./webpack.prod');
//暴露
module.exports = {
    ...ProdConfig,
    //打包模式
    mode: 'development',
    //配置开发服务器
    devServer: {
        //主机地址:
        host: 'localhost',
        //端口号
        port: 3000,
        //是否自动打开浏览器
        open: true
    },
    //源代码和构建后的代码需要产生一个映射关系
    devtool: 'cheap-module-source-map'
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/665124.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

车载以太网 - 网络层 - IPv4/IPv6

目录 一、网络层基本信息介绍 1、网络协议适用范围 2、IPv4和IPv6的地址 3、Ethernet Frames 的类型 二、两种类型IP地址的定义: ECU通信的几种方式 路由器(Router)和IP 地址的概念 路由实例介绍 三、IPv4地址介绍 地址分类&#xff1a; 各类型IP可支持的最大网络数…

C语言实现移位密码

一.移位密码 移位密码(Caesar Cipher)也叫凯撒密码是一种简单的加密技术&#xff0c;它通过将明文中的每个字母按照指定的位数进行移位&#xff0c;从而生成密文。例如&#xff0c;在一个"左移3位"的移位密码中&#xff0c;文中的每个字母都向左移动3个位置&#xff…

7.2 SpringBoot实现上传图片API + url映射本地路径registry.addResourceHandler

文章目录 前言一、url映射本地路径二、上传图片API2.1 接口UploadService2.2 实现类UploadServiceImpl2.3 上传图片Controller 三、测试最后 前言 在图书借阅系统里&#xff0c;有很多图片需要前端展示&#xff0c;这些图片大都是由用户上传&#xff0c;保存在服务端&#xff…

chatgpt赋能python:Python拆数程序:如何快速分解数字?

Python拆数程序&#xff1a;如何快速分解数字&#xff1f; 在计算机编程中&#xff0c;数字拆分是一个非常重要的概念。拆分数字可以让我们更好地理解数字格式&#xff0c;进行计算和分析。而Python作为一种功能强大的编程语言&#xff0c;提供了许多高效的工具来帮助我们快速…

【备战秋招】每日一题:华东师范大学保研机试-2022-罗马数字

为了更好的阅读体检&#xff0c;可以查看我的算法学习博客罗马数字 题目内容 罗马数字是古罗马使用的记数系统&#xff0c;现今仍很常见。 罗马数字有七个基本符号: I,V,X,L,C,D,M。 罗马数字IVXLCDM对应的阿拉伯数字1510501005001000 需要注意的是罗马数字与十进位数字的…

chatgpt赋能python:Python拆分语句,让数据处理更有效率

Python 拆分语句&#xff0c;让数据处理更有效率 Python是一种强大的编程语言&#xff0c;不仅支持各种应用开发&#xff0c;而且非常适合数据处理。Python的易用性和灵活性使其成为了数据科学家和工程师首选的编程语言之一。Python的字符串拆分功能能够轻松处理数据的分割和组…

从C语言到C++_20(仿函数+优先级队列priority_queue的模拟实现+反向迭代器)

目录 1. priority_queue的模拟实现 1.1 未完全的priority_queue 1.2 迭代器区间构造和无参构造 1.3 仿函数的介绍和使用 1.4 完整priority_queue代码&#xff1a; 1.5 相关笔试选择题 答案&#xff1a; 2. 反向迭代器 2.1 反向迭代器的普通实现 reverse_iterator.h&a…

性能测试基础知识(一)性能测试策略

性能测试策略 一、什么是性能测试&#xff1f;二、性能测试的目的三、性能测试策略1、基准测试2、并发测试3、负载测试4、压力测试5、其他测试 一、什么是性能测试&#xff1f; 性能测试是在一定的负载1条件下&#xff0c;系统的响应时间等特性是否满足特定的性能需求。需要有…

软考A计划-系统集成项目管理工程师-信息化知识(二)

点击跳转专栏>Unity3D特效百例点击跳转专栏>案例项目实战源码点击跳转专栏>游戏脚本-辅助自动化点击跳转专栏>Android控件全解手册点击跳转专栏>Scratch编程案例点击跳转>软考全系列 &#x1f449;关于作者 专注于Android/Unity和各种游戏开发技巧&#xff…

【高危】Apache Nifi JMS组件存在JNDI反序列化漏洞

漏洞描述 Apache NiFi 是一个开源的数据流处理和自动化工具&#xff0c; JndiJmsConnectionFactoryProvider 控制器组件用于配置 JMS 连接地址。 Apache NiFi 1.8.0 至 1.21.0 版本中&#xff0c;由于 JndiJmsConnectionFactoryProvider 控制器服务允许已授权的用户配置 URL…

NUCLEO-F411RE RT-Thread 体验 (3) - GCC环境 uart驱动的移植以及console的使用

NUCLEO-F411RE RT-Thread 体验 (3) - GCC环境 uart驱动的移植以及console的使用 1、准备工作 在第一节里&#xff0c;我们用stm32cubemx将pa2 pa3管脚配置成usart2&#xff0c;用于跟st-link虚拟串口的打印用&#xff0c;那么我们先重定向printf函数&#xff0c;看这条通道是…

创建 Python 脚本以在 Linux 中打开新终端并运行命令

文章目录 创建在 Linux 中打开新终端并运行命令的 Python 脚本在 Linux 中创建 Python 脚本来检查 Python 版本使打开的终端保持活动状态并在其中运行命令的 Python 脚本在 Linux 中使用 Python 子模块 subprocess() 将命令传递到新终端总结 Linux 操作系统以其程序员广泛使用的…

PB9如何实现datawindow打印导出PDF,PB导出PDF

PB9如何实现datawindow打印导出PDF&#xff0c;PB导出PDF&#xff1f; 之前的saveas导出pdf&#xff0c;设置非常麻烦。需要 1. 安装gs705w32.exe 2. 安装虚拟打印机 Sybase\Shared\PowerBuilder\drivers\ADIST5.INF 手动添加打印机 这个方法现在对于win64不支持。 今天客…

window11 + python3.7+NVDIA11.7 +pytorch GPU 加速环境配置

window11 python3.7NVDIA11.7 pytorchGPU 加速环境配置 关于pytorch配置GPU环境我在网上看了很多&#xff0c;其实现在基本上没有windows 11 版本环境的配置但是其实没必要担心这个&#xff0c;这没有影响。 对于博主呢&#xff0c;其实不太像配置GPU的&#xff0c;因为其实…

【MYSQL篇】一文弄懂mysql索引原理

文章目录 索引是什么&#xff1f;索引定义索引类型 索引存储模型推演二分查找二叉查找树&#xff08; Binary Search Tree&#xff09;平衡二叉树&#xff08;AVL Tree&#xff09;多路平衡查找树&#xff08;B Tree&#xff09;B树&#xff08;加强版B Tree&#xff09; 小结 …

PyQt中数据库的访问(一)

访问数据库的第一步是确保ODBC数据源配置成功&#xff0c;我接下来会写数据源配置的文章&#xff0c;请继续关注本栏&#xff01; &#xff08;一&#xff09;数据库连接 self.DBQSqlDatabase.addDatabase("QODBC") self.DB.setDatabaseName("Driver{sqlServer…

shell 实现子进程多任务,进程高并发

多进程的作用 提高程序的效率&#xff1a;一些CPU密集型的任务&#xff0c;如数据处理、解压、加密等&#xff0c;使用多进程可以提高程序的执行效率&#xff0c;更快地完成计算任务&#xff1b; 实现更复杂的功能&#xff1a;多进程可以在同一时间向不同的方向处理不同的任务…

SpringBoot创建和运行

1、什么是SpringBoot1.1、优点 2、项目创建2.1、使用Idea创建2.2、使用网页创建 3、项目目录介绍4、项目运行5、包路径错误 1、什么是SpringBoot Spring是为了简化Java程序开发的。Spring Boot是一种用于快速构建独立、生产级别的Java应用程序的开源框架&#xff0c;是为了简化…

MySQL优化--undo log和redo log的区别

首先我们需要知道两个概念 缓冲池&#xff08;buffer pool&#xff09;:主内存中的一个区域&#xff0c;里面可以缓存磁盘上经常操作的真实数据&#xff0c;在执行增删改查操作时&#xff0c;先操作缓冲池中的数据&#xff08;若缓冲池没有数据&#xff0c;则从磁盘加载并缓存…

MySQL数据库基础 13

第十三章 约束 1. 约束(constraint)概述1.1 为什么需要约束1.2 什么是约束1.3 约束的分类 2. 非空约束2.1 作用2.2 关键字2.3 特点2.4 添加非空约束2.5 删除非空约束 3. 唯一性约束3.1 作用3.2 关键字3.3 特点3.4 添加唯一约束3.5 关于复合唯一约束3.5 删除唯一约束 4. PRIMARY…