Promise
Promise 它表示一个异步操作操作最终成功或者失败。其本质上是一个函数返回的对象,可以在上面绑定回调函数,如此就不需要在一开始将回调函数当作参数传入该异步函数了。
传统的回调函数的使用
// 成功的回调函数
function successCallback(result) {
console.log('音频文件创建成功: ' + result)
}
// 失败的回调函数
function failureCallback(error) {
console.log('音频文件创建失败: ' + error)
}
;(function (audioSettings, callback1, callback2) {
setTimeout(() => {
console.log(audioSettings)
if (audioSettings > 5) {
console.log('successCallback')
callback1('successCallback')
} else {
console.log('failureCallback')
callback2('failureCallback')
}
}, 1000)
})(4, successCallback, failureCallback)
// =>4
// =>failureCallback
// =>音频文件创建失败: failureCallback
promise特点
- Promise 的构造器接收一个执行函数(executor),我们可以在这个执行函数里手动地 resolve 和 reject 一个 Promise;一个表示fulfilled,一个表示rejected后的回调函数。【两个函数参数】
- 在本轮 事件循环 运行完成之前,回调函数是不会被调用的。
- 即使异步操作已经完成(成功或失败),在这之后通过 then() 添加的回调函数也会被调用
- 通过多次调用 then() 可以添加多个回调函数,它们会按照插入顺序进行执行,即链式调用
// 上例改成promise调用
function createAudioFileAsync(audioSettings) {
return new Promise((resolve, reject) => {
setTimeout(() => {
console.log(audioSettings)
if (audioSettings > 5) {
console.log('successCallback')
resolve('successCallback')
} else {
console.log('failureCallback')
resolve('failureCallback')
}
}, 1000)
})
}
createAudioFileAsync(4).then(successCallback, failureCallback)
Promise组合工具
-
Promise.resolve()/Promise.reject()
可以通过手动返回成功或者失败的回调结果:
Promise.resolve()
手动设置异步成功执行的结果,直接Promise.resolve返回值
const promise1 = Promise.resolve(123);
promise1.then((value) => {
console.log(value);
// expected output: 123
});
Promise.reject()
手动设置异步失败执行的结果,直接Promise.reject返回值
function resolved(result) {
console.log('Resolved');
}
function rejected(result) {
console.error(result);
}
Promise.reject(new Error('fail')).then(resolved, rejected);
// expected output: Error: fail
- Promise.all()
Promise.all([func1(), func2(), func3()])
.then(([result1, result2, result3]) => {
/* use result1, result2 and result3,全部返回,一起用 */ });
该组合函数表示,等待异步函数func1,func2,func3
三个函数都返回结果之后再,执行.then()函数;
适用于需要多个接口返回接口后,才执行某个触发的场景,如多个接口返回数据,然后取消loading。
const func1 = new Promise((resolve, reject) => {
setTimeout(() => {
resolve(1)
}, 1000)
})
const func2 = new Promise((resolve, reject) => {
setTimeout(() => {
resolve(2)
}, 2000)
})
const func3 = new Promise((resolve, reject) => {
setTimeout(() => {
resolve(3)
}, 3000)
})
console.time('time') // console.time(XXX)和console.timeEnd(XXX)中参数需保持一致
const promiseAll = Promise.all([func1, func2, func3])
.then((res) => {
console.timeEnd('time') // 耗时三秒,说明以最长时间之后才执行.then()回调函数
console.log(res)
})
.catch((err) => {
console.log(err)
})
// =>time: 3002.290ms 耗时三秒
// =>[ 1, 2, 3 ]
- promise.race()
Promise.all([func1(), func2(), func3()])
.then(([result1, result2, result3]) => {
/* result1, result2 and result3,谁先返回,就用谁 */
});
Promise.race()表示多个异步函数中,哪个函数先返回结果,就直接以该结果,进行.then()的回调函数的执行;
const func1 = new Promise((resolve, reject) => {
setTimeout(() => {
resolve(1)
}, 1000)
})
const func2 = new Promise((resolve, reject) => {
setTimeout(() => {
resolve(2)
}, 2000)
})
const func3 = new Promise((resolve, reject) => {
setTimeout(() => {
resolve(3)
}, 3000)
})
console.time('time')
const promiseAll = Promise.race([func1, func2, func3])
.then((res) => {
console.timeEnd('time')
console.log(res)
})
.catch((err) => {
console.log(err)
})
// 时间不一定严格为1秒钟,因为本身setTimeout,或者setInterVal()等宏任务就需要等待执行时间
// =>time: 1006.057ms
// =>1
.catch()
注意:
- 只要.then()抛出异常,就立即停止后续代码的执行,直接被.catch()捕获异常;
new Promise((resolve, reject) => {
console.log('初始化');
resolve();
})
.then(() => {
throw new Error('有哪里不对了');
console.log('第一个回调then');
})
.catch(() => {
console.log('第二个回调catch');
})
.then(() => {
console.log('执行第三个回调then,无论前面发生了什么');
});
// =>初始化
// =>第二个回调catch
// =>执行第三个回调then,无论前面发生了什么
- 错误传递,如果回调函数中有异常抛出,会顺延寻找后续的第一个.catch(),执行抛错后的操作,在此之前的.then()回调都不会执行,如果没有.catch(),则抛错后不会执行后续的回调,浏览器控制台会捕获异常;
new Promise((resolve, reject) => {
console.log('初始化');
resolve();
})
.then(() => {
throw new Error('有哪里不对了');Ï
console.log('异常抛出,此行不执行');
})
.then(() => {
console.log('未找到异常捕获回调,不执行');
}).then(() => {
console.log('未找到异常捕获回调,不执行');
}).catch(() => {
console.log('找到异常捕获回调,执行此行');
}).catch(() => {
console.log('异常前面已捕获,不执行');
})
// =>初始化
// =>找到异常捕获回调,执行此行
// =>Promise {<fulfilled>: undefined}