语法、promise的两个属性、状态属性的三个值以及规则、then之后的返回值、promise函数同步但是then方法内部代码是异步执行
主要应用是封装ajax操作
Promise是es6引入的异步编程的新的解决方案,通过封装异步操作并可以获取成功或者失败的结果。Promise提供统一的api。Promise对象有两个属性,一个是PromiseState,代表的是状态,一个是PromiseResult,代表的是内容
新建一个promise构造函数,函数接受一个函数作为参数,同时该函数有两个参数,reject和resolve。执行异步操作,成功执行resolve(),状态变成resolved状态;失败执行reject(),状态变成rejected状态。无论成功还是失败都可以通过.then()指定成功和失败的回调函数,catch只能调用失败的回调函数。
promise的三个状态:pending,表示进行中,fulfilled也是resolved,表示成功,rejected,表示失败。只能从pending->resolved或者pending->rejected。构造函数中的 resolve 或 reject 只有第一次执行有效,多次调用没有任何作用,即promise 状态一旦改变则不能再变。
Promise是可以链式回调,而且是可以回调穿透的,回调穿透的意思是可以连续调then方法,只在最后加上catch方法就可以了。
为什么说promise是解决异步编程:在then方法中的内容是异步执行的,即走到then方法之后是可以继续执行和then同级的下编代码,再去执行then里面的代码,所以是实现异步编程。简而言之,执行到then方法之后,不用等到then方法中回调函数执行完毕,就可以继续执行跟then平级的下方的代码。
为什么用promise可以解决异步转同步的问题:Promise函数是同步的,但是then里面的函数是异步的。把promise函数中的resolve或者reject中的代码走完,才会触发then方法中的回调函数。这是promise实现异步转化为同步的关键。简而言之,只有把p函数的内容执行完才能执行then里面的回调。
Promise的语法
Const p = new Promise((resolve,reject) => {
If (true) {
resolve(value)
} else {
reject(err)
}
})
p.then(
Value =>{}
reason=>{}
).catch( )
Console.log(‘222’)
Promise函数是同步的,但是then里面的函数是异步的
注:所谓同步代码,就是这行代码不走完不走下一行,但是异步是不走完这一行,下一行也可以走。
const promise = new Promise((resolve, reject) => {
console.log(1)
resolve()
console.log(2)
})
promise.then(() => {
console.log(3)
})
console.log(4)
运行结果:1 2 4 3
构造函数中的 resolve 或 reject 只有第一次执行有效,多次调用没有任何作用,即promise 状态一旦改变则不能再变。
// 调then方法的时候会走进promise函数,
// 如果如果满足a>4就调用resolve方法,触发then方法的第一个回调函数表示成功
// 如果满足a<4,调用reject方法,触发then方法的第二个回调函数表示失败
// catch方法和触发第二个回调其实是一样的,如果触发then的第二个函数,就不再触发
// catch这个回调了
const promise = new Promise((resolve, reject) => {
const a = 3
if (a > 4) {
resolve('success1')
}
if (a < 4) {
reject('error1')
}
if (a > 4) {
resolve('success2')
}
if (a < 4) {
reject('error2')
}
})
promise.then((res) => {
console.log('then: ', res)
}, (reason) => {
Console.log(‘reason:’, reason)).catch((err) => {
console.log('catch: ', err)
})
/*
执行then方法后也是返回一个promise,这个promise对象的结果取决于then方法中的回调函数
1. 如果是throw '',那么afterThen的结果是一个promise,状态是rejected,内容是throw的值
2. 返回的结果是非promise对象,那么状态是fullfilled,内容是返回的内容
3. 返回的结果是promise对象,那么状态和内容取决于返回的promise对象
*/
const p = new Promise((resolve, reject) => {
resolve('ok')
})
const afterThen = p.then(value => {
// 第一种
const obj = {
code: 500
}
throw obj
// 第二种
// return '哈哈哈哈哈哈'
// 第三种
// const p = new Promise((resolve, reject) => {
// // resolve('返回的是promise对象')
// const obj = { error: 'promise返回的reject内容' }
// reject(obj)
// })
// return p
})
console.log('afterThen', afterThen)
第一种打印结果
第二种打印结果
第三种打印结果
promise1 会一直处于挂起状态,所以 () => {console.log(3);} 不会被执行,控制台也不会输出3。 输出结果:1 4
const promise1 = new Promise((resolve, reject) => {
console.log(1);
});
promise1.then(() => {
console.log(3);
});
console.log(4);
promise函数是同步的,所以先打印出来111和222,走完这之后继续同步执行代码,走到promise.then这一行,继续同步执行代码走到后边两个log那两行。最后走到console.log(res)这一行。
const promise1 = new Promise((resolve, reject) => {
console.log(‘111’)
resolve('resolve1')
console.log('222')
})
const promise2 = promise1.then(res => {
console.log(res)
})
console.log('promise1:', promise1); // 这是一个promise对象,包含状态和resolve的内容
console.log('promise2:', promise2);
输出结果
封装ajax操作
onPromiseAjax () {
let p = new Promise((resolve, reject) => {
const xhr = new XMLHttpRequest()
xhr.open('get', 'http://127.0.0.1:8263/todo')
xhr.send()
xhr.onreadystatechange = function () {
if (xhr.readyState === 4) {
if (xhr.status === 200) {
resolve(xhr.response)
} else {
reject(xhr.status)
}
}
}
})
console.log('p-->>', p)
p.then(value => {
console.log(value)
}, reason => {
console.log(reason)
})
},
// 异步转同步第一种:将一个函数当作另一个主函数的参数来使用的函数
// 执行完changeOne函数后再执行changeTwo函数
change () {
this.changeOne(this.changeTwo)
},
changeOne (callback) {
console.log('执行了changeOne') // changeOne的所有代码逻辑,也可以有很多行
callback()
},
changeTwo () {
console.log('执行了changeTwo')
},
// 异步转同步第二种:将先执行的函数作为一个promise进行使用
// 原理:promise函数是一个同步函数,需要先把promise函数内部的代码走完,
// 才会执行then里面的代码。即把resolve的代码走完(成功这种情况)才会触发then
// 方法下的第一个成功的回调。从而实现同步转为异步
// 执行完onSubmitToServer再执行onSkip函数
hello () {
this.onSubmitToServer().then(() => {
this.onSkip()
})
},
onSubmitToServer () {
return new Promise((resolve) => {
resolve(
console.log('执行了第一个方法onSubmitToServer的内容')
)
})
},
onSkip () {
console.log('执行了第二个方法onSkip的内容')
},
// 第三种通过async和await方法
// async和await是配套使用的,await必须写在async函数的内部
// await只能处理Promise对象的异步等待(别的setTimeout,load等造成的异步不能被处理,如果这些异步也想要被处理成同步等待,只能放在Promise里面)
readSync () {
return new Promise((resolve) => {
resolve(
console.log('执行readSync方法'),
console.log('执行readSync方法--again')
)
})
},
async readAsync () {
// 调用异步方法
await this.readSync()
// 异步等待 同步执行:需要把readSync方法内部的走完才会走下边的js代码
console.log('执行readAsync方法')
console.log('end ...')
}