同步语句就是语句执行完成之前,后面的语句不执行。
异步语句就是,执行后,js引擎会产生一个异步对象,后米娜的语句不会等待异步对象执行完成,会直接执行。
我们之前settimeout、事件、nodejs基本上所有操作都是异步、数据库的所有操作都是异步。
我们通常需要异步操作以同步的方式去执行(以及其他的异步执行方式)。
之前我们只能一种手段区管理异步,就是回调函数。
let chengji = 0;
setTimeout(function () {
chengji = Math.floor(Math.random() * 101);
if (chengji >= 60) {
console.log('第一次考试及格了,分数是:' + chengji);
} else {
setTimeout(function () {
chengji = Math.floor(Math.random() * 101);
if (chengji >= 60) {
console.log('第二次考试及格了,分数是:' + chengji);
} else {
console.log('补考也不及格')
}
}, 1000)
}
}, 1000)
如果需要同步执行的异步操作数量很多,那么 回调函数嵌套的层数也会很多,不利于阅读、修改。这个就叫做"回调地狱"。
es6为了解决回调地狱的问题,引入了promise对象及对应的语法糖来解决。
Promise对象
Promise对象是es6定义的异步操作对象,他的建立方式:
const promise = new Promise();
const promise1 = new Promise(function (resolve, reject) {
})
promise对象在建立的时候,需要一个函数参数。
promise对象建立的时候会立即调用参数(函数)且传入两个方法resolve, reject。
promise对象表示一个异步操作对象,在建立之初promise对象状态是pending(进行中)
promis对象一旦调用了resolve, reject两个方法之一,那么他的状态就会发生改变:
调用resolve()方法,promise对象的状态会从进行中变为fulfilled(已成功)。
调用reject()方法,promise对象的状态会从进行中变为rejected(已失败)。
一个promise对象的状态一旦发生改变就会确定状态,之后不会再次改变。这个变化叫做resolved(已定型)。
所以,可以认为promise对象是一个状态机。
promise对象封装的内容可以不是异步,如果
如下是一个简单的异步操作:
let chengji = 0;
setTimeout(function () {
chengji = Math.floor(Math.random() * 101);
}, 1000)
用promise封装:
let chengji = 0;
const promise = new Promise(function (resolve, reject) {
setTimeout(function () {
chengji = Math.floor(Math.random() * 101);
if (chengji >= 60) {
resolve(chengji)
} else {
reject(chengji)
}
},1000)
})
封装后,原本的异步操作也是立即执行。
好处是产生了一个promise对象,这个对象在异步操作结束时,状态就确定了。我们可以在任何时候去查看结果
promise
.then(function(result) {
console.log('及格了,成绩是:' + result)
})
.catch(function(err) {
console.log('不及格,成绩是:' + err)
})
.finally(function() {
})
promise对象的.then方法是成功后执行的,catch是失败后执行的,可以获取参数。
finally方法是只要有结果,无论成功或是失败都会执行,没有参数的。
Promise的then方法
then方法可以监控成功和失败的状态:
new Promise().then((result)=>{
//成功时
},(err){
//失败时
})
但是一般情况下,then只监控成功。
then、catch、finally都会返回Promise,因此,写法上可以采用链式操作。
Promise的catch方法
new Promise().catch(err=>{
//失败时
})
catch方法用来监控失败时。
Promise的finally方法
new Promise().finally(()=>{
//无论成功失败都会执行的。
})
Promise.all()
Promise.all()方法接受一个数组(或具有遍历器接口的结构)作为参数,内容也是Promise对象。
Promise.all()将多个Promise对象组合成一个新的Promise,
这个新的Promise对象的结果:如果所有成员的结果都是成功,则算作成功,返回每个成员的输出(以数组的方式)。如果有任何一个成员失败,则整体失败,返回值是失败的成员的返回值。
let arr = [];
arr.push(new Promise((resolve, reject) => {
resolve('第一个成功了');
}))
arr.push(new Promise((resolve, reject) => {
resolve('第二个成功了')
}))
arr.push(new Promise((resolve, reject) => {
resolve('第三个成功了');
}))
let p = Promise.all(arr);
p.then(result => {
console.log('then')//三个成员成功了,则会被整体的then接收
console.log(result);//['第一个成功了','第二个成功了','第三个成功了']
}).catch(err => {
console.log('catch')
console.log(err)
}).finally(() => {
})
let arr = [];
arr.push(new Promise((resolve, reject) => {
resolve('第一个成功了');
}))
arr.push(new Promise((resolve, reject) => {
reject('第二个失败了');
}))
arr.push(new Promise((resolve, reject) => {
resolve('第三个成功了');
}))
let p = Promise.all(arr);
p.then(result => {
console.log('then')
console.log(result);
}).catch(err => {
console.log('catch')//因为成员2失败了
console.log(err)//'第二个失败了'
}).finally(() => {
})
如果不使用特殊的方法,那么,多个异步是同时开始的,并不会顺序执行。
Promise.any()
Promise.any()方法接受一个数组(或具有遍历器接口的结构)作为参数,内容也是Promise对象。
Promise.all()将多个Promise对象组合成一个新的Promise,
这个新的Promise对象的结果:如果所有成员的结构都是失败,则算作失败,返回AggregateError: All promises were rejected。如果有任何一个成员成功,则整体成功,返回值是成功的成员的返回值。
Promise.race()
Promise.any()方法接受一个数组(或具有遍历器接口的结构)作为参数,内容也是Promise对象。
Promise.all()将多个Promise对象组合成一个新的Promise,
这个新的Promise对象的结果:整体的结果是首个有结果的成员的结果。
let arr = [];
arr.push(new Promise((resolve, reject) => {
setTimeout(function () {
console.log('第一个成功了');
resolve('第一个成功了')
}, Math.random() * 10000)
}))
arr.push(new Promise((resolve, reject) => {
setTimeout(function () {
console.log('第二个成功了');
resolve('第二个成功了')
}, Math.random() * 10000)
}))
arr.push(new Promise((resolve, reject) => {
setTimeout(function () {
console.log('第三个成功了');
resolve('第三个成功了')
}, Math.random() * 10000)
}))
let p = Promise.race(arr);
p.then(result => {
console.log('then')
console.log('整体:', result);
})
//
//第一个成功了
//then
//整体: 第一个成功了
//第三个成功了
//第二个成功了