回调函数:
因为函数在Javascript中是第一类对象,我们像对待对象一样对待函数,因此我们能像传递变量一样传递函数,在函数中返回函数,在其他函数中使用函数。当我们将一个回调函数作为参数传递给另一个函数是,我们仅仅传递了函数定义。我们并没有在参数中执行函数。我们并不传递像我们平时执行函数一样带有一对执行小括号()的函数。需要注意的很重要的一点是回调函数并不会马上被执行。它会在包含它的函数内的某个特定时间点被“回调”(就像它的名字一样)。任意导致回调地域。
调用回调过早或过完
没能向你的回调传递必要的参数/环境
吞掉可能发生的错误异常
Promise
Promise是一个类,有如下构造器
new Promise(function(resolve,reject){ })
使用了Promise异步完成的任务。被包装的函数必须有resolve和reject的两个参数。
- resolve参数代表异步任务完成后的回调函数 (fulfilled)
- reject参数代表异步任务失败的回调函数 (rejected)
- pending 等待中,初始位置
const myFirstPromise = new Promise((resolve, reject) => {
// 确认异步操作是否执行完成,
// ?做一些异步操作,最终会调用下面两者之一:
//
// resolve(someValue); // fulfilled
// ?或
// reject("failure reason"); // rejected
});
example
let myFirstPromise = new Promise((resolve,reject) => {
setTimeout(() => {
let num = parseInt(Math.random()*200);
if(num > 100 ){
resolve(num)
}
else{
reject(num)
}
}, 2000);
})
resolve和reject都会被promise捕捉到,可以在之后的回调函数中调用 .then。
创建完,如何使用承诺后的结果
Promise 不论成功或失败都会调用 then
catch() 只有当 promise 失败时才会调用
myFirstPromise.then(res => {
// 执行resolve的话,执行这块,
console.log(res)
},err => {
// 执行reject的话,执行这块,
console.log(err)
}
)
//then方法的返回值不是一个promise对象,但会被包装成一个promise,方便链式调用
then 方法的链式调用可以帮忙串行解决一些逻辑问题。当我们书写有顺序的异步事件
$ajax("./a")
$ajax("./b")
$ajax("./c")
$ajax('./a').success(function(res){
$ajax('./b').success(function(res){
$ajax('./c'.success(function(res){
//执行你想要的的操作
}))
})
})
Promise
let promiseA = new Promise((resolve,reject)=>{
$ajax('./a').success(function(res){
resolve(res)
})
})
promiseA.then(res=>{
return new Promise((resolve,reject)=>{
$ajax('./b').success(function(res){
resolve(res)
})
})
}).then(res=>{
return new Promise((resolve,reject)=>{
$ajax('./c').success(function(res){
resolve(res)
})
})
}).then(res=>{
//操作
})
Promise.all 接收一个数组,数组的每一项都是一个promise对象。当数组中所有的promise的状态都达到resolved的时候,Promise.all的状态就会变成resolved,如果有一个状态变成了rejected,那么Promise.all的状态就会变成rejected(任意一个失败就算是失败),这就可以解决我们并行的问题。调用then方法时的结果成功的时候是回调函数的参数也是一个数组,按顺序保存着每一个promise对象resolve执行时的值。
Promise.race 竞速模式 也是接受一个每一项都是promise的数组。但是与all不同的是,第一个promise对象状态变成resolved时自身的状态变成了resolved,第一个promise变成rejected自身状态就会变成rejected。第一个变成resolved的promsie的值就会被使用。就是取决于第一个状态。
async和await
async-await是寄生于Promise,Generator的语法糖
async用于申明一个function是异步的,而await认为是async wait 的简写,等待一个异步方法的完成。
async函数返回的是一个Promise对象
规则
1、async表示这是一个async函数,await只能用在这个函数里;
2、await 表示在这里等待promise返回的结果,再继续执行;
3、await后面跟着的是一个promise对象
场景: Promise Vs Async - Await
1、调用promise1,使用promise1返回的结果去调用promise2,然后使用两者的结果去调用promise3
const makeRequest = () => {
return promise1()
.then(value1 => {
return promise2(value1)
.then(value2 => {
return promise3(value1, value2)
})
})
}
const makeRequest = async () => {
const value1 = await promise1()
const value2 = await promise2(value1)
return promise3(value1, value2)
}
2、Async/Await让try/catch可以同时处理同步和异步错误。在下面的promise示例中,try/catch不能处理JSON.parse的错误,因为它在Promise中。我们需要使用.catch,这样错误处理代码非常冗余。并且,在我们的实际生产代码会更加复杂。
const makeRequest = () => {
try {
getJSON()
.then(result => {
// JSON.parse可能会出错
const data = JSON.parse(result)
console.log(data)
})
// 取消注释,处理异步代码的错误
// .catch((err) => {
// console.log(err)
// })
} catch (err) {
console.log(err)
}
}
const makeRequest = async () => {
try {
// this parse may fail
const data = JSON.parse(await getJSON())
console.log(data)
} catch (err) {
console.log(err)
}
}