这里写目录标题
一、定义
- ES6中重要和好用的特性
- 是异步编程的一种解决方案
- resolve , reject 是函数
- 链式编程
二、什么时候使用
- 一般在有异步操作时,使用Promise对异步操作的封装
- new ----->构造函数(1、保存一些状态信息 2、执行传入的函数)
- 在执行传入的回调函数时,会传入两个参数。resolve 、reject 本身又是函数
可以嵌套:(简单嵌套)
三、Promise的三种状态
- pending:等待状态,比如正在进行网络请求,或者定时器没有到时间;
- fulfill:满足状态,当我们主动回调了resolve时,就处于该状态,并且会回调.then()
- reject:拒绝状态,当我们主动调用reject时,就处于该状态,并且会回调.catch()
//也可以将 resolve reject 调用的放在一起
//如下 可以都放在了then里面 用逗号隔开
new Promise((resolve, reject) => {
resolve("成功");
// reject("失败");
}).then(
(data) => {
console.log(data);
},
(error) => {
console.log(error);
}
);
},
// bad
promise
.then(function(data) {
// success
}, function(err) {
// error
});
// good 要这么写
promise
.then(function(data) { //cb
// success
})
.catch(function(err) {
// error
});
四、链式调用
4.1考虑的是每层都是正确的情况
除了前面2、的简单嵌套
还可以对 对前面数据的处理 再进行下一步
new Promise((resolve, reject) => {
setTimeout(() => {
resolve("111");
}, 1000);
})
.then((res) => {
//1、第一次自己处理代码
console.log(res, "第一层的处理代码"); //输出结果111
// 2、第一次对结果处理
return new Promise((resolve) => {
resolve(res + 222);
});
})
.then((res) => {
//1、第二次自己处理代码
console.log(res, "第二层的处理代码"); //输出结果111222
//2、第二次对结果处理
return new Promise((resolve) => {
resolve(res + 333);
});
})
.then((res) => {
//1、第三次自己处理代码
console.log(res, "第三层的处理代码"); //输出结果111222333
//2、第三次对结果进行处理
return new Promise((resolve) => {
resolve(res + 444);
});
})
.then((res) => {
console.log(res, "第四层的处理代码"); //输出结果111222333444
});
上面的代码可以简写,如下:
//简写 new Promise(resolve => resolve(结果))
new Promise((resolve, reject) => {
setTimeout(() => {
resolve("111");
}, 1000);
})
.then((res) => {
//1、第一次自己处理代码
console.log(res, "第一层的处理代码");
// 2、第一次对结果处理
// return new Promise((resolve) => {
// resolve(res + 222);
// });
return Promise.resolve(res + 222);
})
.then((res) => {
//1、第二次自己处理代码
console.log(res, "第二层的处理代码");
//2、第二次对结果处理
// return new Promise((resolve) => {
// resolve(res + 333);
// });
return Promise.resolve(res + 333);
})
.then((res) => {
//1、第三次自己处理代码
console.log(res, "第三层的处理代码");
//2、第三次对结果进行处理
// return new Promise((resolve) => {
// resolve(res + 444);
// });
return Promise.resolve(res + 444);
})
.then((res) => {
console.log(res, "第四层的处理代码");
});
上面的代码还可以简写,如下:
//还可以更简洁 省略掉Promise.resolve
new Promise((resolve, reject) => {
setTimeout(() => {
resolve("111");
}, 1000);
})
.then((res) => {
//1、第一次自己处理代码
console.log(res, "第一层的处理代码");
// 2、第一次对结果处理
return res + 222;
})
.then((res) => {
//1、第二次自己处理代码
console.log(res, "第二层的处理代码");
//2、第二次对结果处理
return res + 333;
})
.then((res) => {
//1、第三次自己处理代码
console.log(res, "第三层的处理代码");
//2、第三次对结果进行处理
return res + 444;
})
.then((res) => {
console.log(res, "第四层的处理代码");
});
4.2 有一层出现错误(reject)的写法
// 前面考虑的是 每一层都是成功的情况 如果中间有一层是执行失败呢?
// 输出第一次自己处理代码的饿结果和reject的结果
new Promise((resolve, reject) => {
setTimeout(() => {
resolve("111");
}, 1000);
})
.then((res) => {
//1、第一次自己处理代码
console.log(res, "第一层的处理代码"); //输出结果111
// 2、第一次对结果处理
return new Promise((resolve, reject) => {
// resolve(res + 222);
reject("err,对结果第一次处理 出现错误"); //错误结果
});
})
.then((res) => {
//1、第二次自己处理代码
console.log(res, "第二层的处理代码");
//第二次对结果处理
return new Promise((resolve) => {
resolve(res + 333);
});
})
.then((res) => {
//1、第三次自己处理代码
console.log(res, "第三层的处理代码");
//2、第三次对结果进行处理
return new Promise((resolve) => {
resolve(res + 444);
});
})
.then((res) => {
console.log(res, "第四层的处理代码");
})
.catch((err) => {
console.log(err);
});
前面代码的简写:
//前面中间有错误的处理方法一样有简写
new Promise((resolve, reject) => {
setTimeout(() => {
resolve("111");
}, 1000);
})
.then((res) => {
//1、第一次自己处理代码
console.log(res, "第一层的处理代码"); //输出结果111
// 2、第一次对结果处理
// return Promise.reject("err message"); //reject简写
throw "error message"; //这种写法也是一样的
})
.then((res) => {
//1、第二次自己处理代码
console.log(res, "第二层的处理代码");
//第二次对结果处理
return promise.resolve(res + 333);
})
.then((res) => {
//1、第三次自己处理代码
console.log(res, "第三层的处理代码");
//2、第三次对结果进行处理
return Promise.resolve(res + 444);
})
.then((res) => {
console.log(res, "第四层的处理代码");
})
.catch((err) => {
console.log(err);
});
五、promise.all 的使用
(1)写法1
//在两个Promise请求全部得到结果后 才then
//返回的results是数组,数组[0]是第一个promise返回的数据;数组[1]是第二个Promise返回的数据
Promise.all([
new Promise((resolve, reject) => {
setTimeout(() => {
resolve({
name: "第一个请求返回的数据!",
message: "返回的时间是两秒后",
});
}, 2000);
}),
new Promise((resolve, reject) => {
setTimeout(() => {
resolve({
name: "第二个请求返回的数据",
message: "返回的时间是一秒后",
});
}, 1000);
}),
]).then((results) => {
console.log(results);
});
返回的结果:
(2)写法2
下面的方法会简洁一点:
let p1 = new Promise((resolve, reject) => {
let math1 = Math.ceil(Math.random() * 10);
if (math1 > 5) {
resolve(math1);
} else {
reject(math1);
}
});
let p2 = new Promise((resolve, reject) => {
let math2 = Math.ceil(Math.random() * 10);
resolve(math2);
});
let p3 = new Promise((resolve, reject) => {
let math3 = Math.floor(Math.random() * 10 + 1);
resolve(math3);
});
const p = Promise.all([p1, p2, p3]);
p.then((data) => {
console.log("promise.all resolve 返回的结果", data);
// (1)只有p1、p2、p3的状态都变成fulfilled,p的状态才会变成fulfilled,此时p1、p2、p3的返回值组成一个数组,传递给p的回调函数。
}).catch((error) => {
console.log("promise.all reject 结果", error);
// (2)只要p1、p2、p3之中有一个被rejected,p的状态就变成rejected,此时第一个被reject的实例的返回值,会传递给p的回调函数。
});
// 返回的可能结果:
// promise.all resolve 返回的结果 (3) [8, 3, 9]
// promise.all reject 结果 3
六. async/await
基本写法:getInfs() 正常调用这个方法就好
async
和await
是成对出现的- 正常情况:
await
命令后面是一个Promise
对象,返回该对象的结果。如果不是 Promise 对象,就直接返回对应的值。- 另一种情况是,
await
命令后面是一个thenable对象(即定义了then方法的对象),那么await会将其等同于 Promise 对象。- async 的异步操作 要如下写法2 这样写。这样不会由于串联造成的堵塞而浪费时间
fun1() {
return new Promise((resolve) => {
setTimeout(() => {
let data = [1, 2, 3, 4, 5];
resolve(data);
}, 2000);
});
},
fun2() {
return new Promise((resolve) => {
setTimeout(() => {
let data = [1, 3, 5, 7];
resolve(data);
}, 1000);
});
},
fun3() {
return new Promise((resolve) => {
setTimeout(() => {
let data = [2, 4, 6, 8];
resolve(data);
}, 3000);
});
},
async totalTask() {
console.log("开始");
// -------------------- 写法1 ------------------------
// await this.fun1().then((res) => {
// console.log("fun1的返回值是:", res);
// });
// await this.fun3().then((res) => {
// console.log("fun3的返回值是:", res);
// });
// await this.fun2().then((res) => {
// console.log("fun2的返回值是:", res);
// });
// -------------------- 写法2 --------------------------
// 因为写法1的话 要等到fun1 完成才执行fun2 再执行fun3
// 这样写是为了 串行 而造成的堵塞 而浪费时间
let data1 = this.fun1();
let data2 = this.fun2();
let data3 = this.fun3();
await data1.then((res) => {
console.log("111111111", res);
});
await data3.then((res) => {
console.log("3333333333", res);
});
await data2.then((res) => {
console.log("222222222222", res);
});
console.log("await data1-------------:", await data1);// [1, 2, 3, 4, 5]
console.log("data1-------------:", data1); //输出promise对象 如下:
//Promise {<fulfilled>: Array(5)}
//[[Prototype]]: Promise
//[[PromiseState]]: "fulfilled"
//[[PromiseResult]]: Array(5)
async getBooksByPrice(price) {
let bookss = await this.getAllBooks(); //等这一步完成 执行下面的东西
return {
books: bookss.filter((v) => v.price > price),
};
},
btnClick() {
this.getBooksByPrice(100).then((v) => console.log("v", v));
},
七、async await 的错误处理方法
7.1 then - catch
async click() {
console.log("start");
const result = await this.Success();
console.log("result:", result);
await this.UnSuccess()
.then((data) => {
console.log("unSuccess result 信息:", data);
})
.catch((err) => {
console.log("UnSuccess error 信息:", err.message);
})
.then(() => {
console.log("end end");
});
console.log("end");
},
Success() {
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve("Run Success");
}, 1000);
});
},
UnSuccess() {
return new Promise((resolve, reject) => {
setTimeout(() => {
reject(new Error("Run Error"));
}, 500);
});
},
7.2 try - catch
async click3() {
try {
console.log("start------------------");
let result1 = await this.UnSuccess(); //1
console.log("result1:", result1); //1 没有执行
} catch (err) {
console.log("发生错误!");
console.log(err.message);
}
try {
let result2 = await this.Success(); //2
console.log("result2:", result2); //2
} catch (err) {
console.log("发生错误!");
console.log(err.message);
}
console.log("end");
},
Success() {
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve("Run Success");
}, 1000);
});
},
UnSuccess() {
return new Promise((resolve, reject) => {
setTimeout(() => {
reject(new Error("Run Error"));
}, 500);
});
},
7.3 then - catch 结构赋值
async click1() {
console.log("start--------------");
const [err, result] = await this.Success()
.then((result) => [null, result])
.catch((err) => [err, null]);
if (err) {
console.log("获取到的错误信息为:", err);
} else {
console.log("results:", result);
}
console.log("===================");
const [errs, results] = await this.UnSuccess()
.then((res) => [null, res])
.catch((err) => [err, null]);
if (errs) {
console.log("获取的错误信息:", errs);
return;
}
console.log("results", results);
console.log("end--------------");
},
Success() {
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve("Run Success");
}, 1000);
});
},
UnSuccess() {
return new Promise((resolve, reject) => {
setTimeout(() => {
reject(new Error("Run Error"));
}, 500);
});
},
7.4 封装 then - catch 结构赋值
async click() {
console.log("start----------------");
const [err, result] = await this.AsyncHandling(this.UnSuccess);
if (err) {
console.log("发生错误了");
console.log(err);
} else {
console.log("result:", result);
}
const [err2, result2] = await this.AsyncHandling(this.Success);
if (err2) {
console.log("又发生错误了");
console.log(err2);
} else {
console.log("result2:", result2);
}
console.log("end");
},
AsyncHandling(asyncFn) {
return asyncFn()
.then((result) => [null, result])
.catch((err) => [err, null]);
},
Success() {
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve("Run Success");
}, 1000);
});
},
UnSuccess() {
return new Promise((resolve, reject) => {
setTimeout(() => {
reject(new Error("Run Error"));
}, 500);
});
},