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
暂存区中的文件列表
clear
或ctrl + 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)
- 分别暴露:export 变量声明
-
3.2 导入
- 适合于(分别暴露和统一暴露)的导入形式有两种:
- 通用形式的导入:
import * as 别名 from '子模块文件路径'
这里的*表示所有,as表示别名 from来自于哪一个目标文件 - 解构形式的导入:
import {} from '子模块文件路径'
{}里面写什么是子模块中export后面的变量名
- 适合于默认暴露的导入形式有两种:
- 通用形式的导入:
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 () {
4、throw抛出的错误,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 返回值 PromiseResult为undefined
2、如果返回的是另一个新promise, 此promise的结果就会成为新promise的结果
(当下这个新的Promise对象的状态将决定于then方法返回的Promise对象的状态,结果值亦然)
3、如果抛出异常,新promise变为rejected, reason为抛出的异常
const p = new Promise((resolve,reject)=>{
resolve('ok');
});
let result = p.then(value=>{
1、throw '错误信息';// 1抛出异常 错误
2、return 100; // 值可以是字符串、数字、boolean、null、undefined、数组、对象都变为PromiseResult的结果
3、return 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'
}