- 首先定义一个函数
let func1 = () => new Promise((resolve, reject) => setTimeout(() => resolve(12345), 1000))
函数func1执行的时候,会返回一个promise对象
let func1 = () => new Promise((resolve, reject) => setTimeout(() => resolve(12345), 1000))
let result = func1()
console.log(result);
- 使用async和await后
let func1 = () => new Promise((resolve, reject) => setTimeout(() => resolve(12345), 1000))
// 当且仅当async修饰函数后,函数内可以使用await,await后面可以跟一个返回promise的函数
async function func2() {
// await会拿到resolve结果,是then函数的语法糖
let res = await func1()
console.log(res);
}
func2()
一秒钟之后打印出12345
- 上面的函数可以写成这样的形式
let func1 = () => new Promise((resolve, reject) => setTimeout(() => resolve(12345), 1000))
function func2() {
func1().then(res => console.log(res))
}
func2()
在1秒钟之后会打印出12345
async + await(是promise + then的语法糖)(可以认为是generator函数的语法糖)
上面两种方式是等价的,只不过使用async和await可以像同步编程一样整理代码逻辑,不想then那样回调地狱
await拿的是resolve的数据或者说传给then的数据,reject的需要靠try…catch
async function main() {
try {
var data1 = await query(sql)
...
var data2 = await query(sq2)
...
var data3 = await query(sq3)
} catch(e) {
console.log(e)
}
}
这样可以对三条语句同时处理错误
- 使用async await处理异步请求
async function get() {
let user = await ajax('/user')
// 等待user请求回来之后,再请求lesson
let lessons = await ajax('/lessons')
// lessons请求回来之后再进行其它的操作
console.log(lessons)
}
get()
- async延时函数
function sleep(delay = 2000) {
return new Promise(resolve => {
setTimeout(() => {
resolve();
}, delay)
})
}
async function show() {
for (let value of ['hello', 'world', '123']) {
// 延迟2秒之后再打印
await sleep();
console.log(value);
}
}
show()
- class与await结合
如果一个类中包含一个then方法,那么这个then就会包装成一个Promise
class User {
constructor(name) {
this.name = name;
}
then(resolve, reject) {
let user = ajax(`http://localhost3000/user?name=${this.name}`);
resolve(user);
}
}
async function get() {
// 名字请求回来之后在打印
let user = await new User('xiaoming');
console.log(user);
}
get()
- await并行执行技巧
function func1() {
return new Promise(resolve => {
setTimeout(() => {
resolve(123)
}, 2000)
})
}
function func2() {
return new Promise(resolve => {
setTimeout(() => {
resolve(456)
}, 2000)
})
}
async function demo() {
let h1 = func1();
let h2 = func2();
let result1 = await h1;
let result2 = await h2;
// 这样func1和func2就可以一起执行,得到他们的结果后再打印,还可以通过Promise.all实现
console.log(result1, result2);
}
demo()
通过Promise.all实现
function func1() {
return new Promise(resolve => {
setTimeout(() => {
resolve(123)
}, 2000)
})
}
function func2() {
return new Promise(resolve => {
setTimeout(() => {
resolve(456)
}, 2000)
})
}
async function demo() {
let result = await Promise.all([func1(), func2()])
console.log(result);
}
demo()
Promise规范–all
all方法用于监听多个Promise对象
参数是一个数组,数组中的每一项都是一个Promise对象
我们可以通过then方法监听状态的改变
如果所有的操作都执行成功,才会执行success方法
如果有一个操作执行失败,则会执行fail方法
不论是成功还是失败,返回值是数组,数组中的每一个成员对应每一个Promise返回的数据
Promise规范–race
race方法用于监听多个Promise对象
参数是一个数组,数组中的每一项都是一个Promise对象
我们可以通过then方法监听状态的改变(监听第一个Promise对象状态的改变)
如果有一个请求执行成功,就会执行success方法
如果有一个请求执行失败,则会执行fail方法
返回值是状态改变的时候传递的数据
Promise.allSettled
等到所有promises都已敲定(settled)(每个promise都已兑现(fulfilled)或已拒绝(rejected))。
返回一个promise,该promise在所有promise完成后完成。并带有一个对象数组,每个对象对应每个promise的结果。
Promise规范
Promise是将异步写法变为同步写法的规范
只是写法的改变,操作并没有改变
异步操作:在回调函数中,一层嵌套一层
同步操作:将方法写在外部
三个状态
pending 表示操作正在执行 resolved 表示操作执行成功 rejected 表示操作执行失败
状态的流向:在Promise中状态有两个方向的流动:
状态由pending流向resolved,说明操作执行成功完毕
状态由pending流向rejected,说明操作执行失败完毕
语法: new Promise((resolve, reject) => {回调函数中执行异步操作})
如果操作执行成功,执行resolve方法 如果操作执行失败,执行reject方法
在外部通过then方法监听状态的改变
then(success, fail) 该方法接收两个参数
success:表示成功时候执行的回调函数,参数是由resolve方法执行的时候传递的参数(只能传递一个),想 传递多个可以放在数组中
fail:表示失败时候执行的回调函数,参数是由reject方法执行的时候传递的参数(只能传递一个)
then方法的返回值是Promise对象,因此,可以链式调用该方法
上一个then方法的输出,将作为下一个then方法参数的输入。如果操作已经执行完毕,then方法也会立即执行
有三个方法可以监听Promise状态:
then:可以监听状态成功或者是失败的方法
定义多个then方法,此时后一个then方法可以监听前一个then的成功与失败
catch:可以监听状态失败时候的方法
失败只能被监听一次,但是可以被后面的then继续监听
finally:无论成功还是失败都会执行的方法
无法接收数据
Promise规范--all
all方法用于监听多个Promise对象
参数是一个数组,数组中的每一项都是一个Promise对象
我们可以通过then方法监听状态的改变
如果所有的操作都执行成功,才会执行success方法
如果有一个操作执行失败,则会执行fail方法
不论是成功还是失败,返回值是数组,数组中的每一个成员对应每一个Promise返回的数据
Promise规范--race
race方法用于监听多个Promise对象
参数是一个数组,数组中的每一项都是一个Promise对象
我们可以通过then方法监听状态的改变(监听第一个Promise对象状态的改变)
如果有一个请求执行成功,就会执行success方法
如果有一个请求执行失败,则会执行fail方法
返回值是状态改变的时候传递的数据
Promise规范--resolve与reject
resolve是Promise的静态方法,返回一个可以监听resolved状态的Promise对象
参数有三种:
js数据,此时then方法会立即执行(then方法接收的数据就是该数据)
promise对象
thenable参数(带有then方法的对象)
reject是Promise的静态方法,返回一个可以监听rejected状态的对象
then方法监听失败时候,回调函数的参数就是reject方法参数(错误的描述信息)
不论reject方法是什么数据,then都将执行失败的回调函数
简单实现Promise
// 实现promise
function MyPromise(callBack) {
// 维护状态
this.status = 'pending';
// 存储回调函数
this.successArray = [];
this.failArray = [];
// 定义resolve和reject方法
// 成功
let resolve = (value) => {
// 改变状态
this.status = 'resolved';
// 执行回调函数
this.successArray.forEach(fn => value = fn(value))
this.successArray = [];
this.value = value;
}
// 失败
let reject = () => {
this.status = 'rejected';
this.failArray.forEach(fn => value = fn(value))
this.failArray = [];
this.value = value
}
// 执行回调函数
try {
callBack(resolve, reject);
} catch(e) {
// 有错误就失败了
reject(e);
}
}
// 原型方法
MyPromise.prototype.then = function(success, fail) {
if (this.status === 'pending') {
success && this.successArray.push(success);
fail && this.failArray.push(fail);
} else if (this.status === 'resolved') {
success && success(this.value);
} else {
fail && fail(this.value);
}
// 链式调用
return this;
}