目录
finally回调函数:返回上一次的Promise对象值/promise包装的error
allSettled() :多个不依赖于彼此成功完成的异步任务时,或者:想知道每个 promise 的结果时
all:当异步操作之间不存在结果的依赖时,all中的所有方法是一同执行的
Promise.resolve(值):如果该值本身就是一个 promise实例,将直接被返回
constructor的函数参数:起始函数;同步(立即执行)
起始函数的函数参数(均可选):resolve (起始函数成功时调用)、reject(失败时调用)
隐式return 原promise对象/ 显式return (非promise会包装成promise)
promise对象变成reject状态时,整个async函数会中断
promise应用:webpack loader
promise手写
Promise.prototype(实例)方法
均返回promise
then回调函数:
resolveFn的形参=resolve的参数
catch回调函数:
rejectFn的形参=reject的参数
promise.then(f1).catch(f2);
//f1 和 f2处于同一层级,二者只会执行其一,下面没有链,所以 error 不会被处理。
promise.then(f1, f2);
异常穿透:错误的传递(就近的 onRejected
/catch)
一遇到异常抛出,浏览器就会顺着 Promise 链寻找下一个就近的 onRejected
失败回调函数或者由 .catch()
指定的回调函数。
new Promise((resolve, reject) => {
reject('失败了')
})
.then(
(data) => { console.log('onResolved1', data); },
(error) => { console.log('onRejected2', error); }
)
.catch(
(error) => {
console.log('catch', error)
}
)
"失败了"
就会被离它最近的 then 中的 onRejected
函数所处理,而不会被 catch 所捕获。
finally回调函数:返回上一次的Promise对象值/promise包装的error
Promise并发方法
allSettled()
:多个不依赖于彼此成功完成的异步任务时,或者:想知道每个 promise 的结果时
all
:当异步操作之间不存在结果的依赖时,all中的所有方法是一同执行的
const promise1 = Promise.resolve(3);
const promise2 = 42;
const promise3 = new Promise((resolve, reject) => {
setTimeout(resolve, 100, 'foo');//setTimeout(function[, delay, arg1, arg2, ...]);
});
Promise.all([promise1, promise2, promise3]).then((values) => {
console.log(values);
});
// Expected output: Array [3, 42, "foo"]
race:只保留第一个结果,其他的方法仍在执行
any:其中一个成功结果,都失败则报错
map:promise.reslove(catch)
catch方法返回的promise实例会被promise.reslove()包裹,这样传进promise.all的数据都是resolved状态的。
let p1 = Promise.resolve(1)
let p2 = Promise.resolve(2)
let p3 = Promise.resolve(3)
let p4 = Promise.resolve(4)
let p5 = Promise.reject("error")
let arr = [p1,p2,p3,p4,p5];
let all = Promise.all(arr.map((promise)=>promise.catch((e)=>{console.log("错误信息"+e)})))
all.then(res=>{console.log(res)}).catch(err=>console.log(err));
观察者模式
const p1 = new Promise((resolve, reject) => {
setTimeout(() => {
resolve('result')
},
1000);
})
p1.then(res => console.log(res), err => console.log(err))
分析Promise的调用流程:
Promise
的构造方法接收一个executor()
,在new Promise()
时就立刻执行这个executor回调executor()
内部的异步任务被放入宏/微任务队列,等待执行then()
被执行,收集成功/失败回调,放入成功/失败队列executor()
的异步任务被执行,触发resolve/reject
,从成功/失败队列中取出回调依次执行
观察者模式:收集依赖 -> 触发通知 -> 取出依赖执行
在Promise里,执行顺序是then收集依赖 -> 异步触发resolve -> resolve执行依赖
。
class MyPromise {
// 构造方法接收一个回调
constructor(executor) {
this._resolveQueue = [] // then收集的执行成功的回调队列
this._rejectQueue = [] // then收集的执行失败的回调队列
/*由于resolve/reject是在executor内部被调用,
因此需要使用箭头函数固定this指向, 否则找不到this._resolveQueue*/
let _resolve = (val) => {
// 从成功队列里取出回调依次执行
while(this._resolveQueue.length) {
const callback = this._resolveQueue.shift()
callback(val)
}
}
// 实现同resolve
let _reject = (val) => {
while(this._rejectQueue.length) {
const callback = this._rejectQueue.shift()
callback(val)
}
}
// new Promise()时立即执行executor,并传入resolve和reject
executor(_resolve, _reject)
}
// then方法,接收一个成功的回调和一个失败的回调,并push进对应队列
then(resolveFn, rejectFn) {
this._resolveQueue.push(resolveFn)
this._rejectQueue.push(rejectFn)
}
}
创建Promise实例
await 值=Promise.resolve(值)
Promise.resolve(值):如果该值本身就是一个 promise实例,将直接被返回
Promise.reject(值)
constructor的函数参数:起始函数;同步(立即执行)
起始函数的函数参数(均可选):resolve (起始函数成功时调用)、reject(失败时调用)
状态:都没有的话,状态为pending[待定]初始状态
//什么都不输出
new Promise(()=>{}).then(()=>{
console.log("then")
}).finally(()=>{
console.log("finally")
})
【建议星星】要就来45道Promise面试题一次爽到底(1.1w字用心整理) - 掘金
错误无法捕获
异步回调中:promise已结束
在延时等待 1s 后,抛出错误这一操作才会执行,但此时外面的 Promise 早就执行结束。
因此,promise 无法处理它,程序会在此崩掉。
new Promise((resolve, reject) => {
setTimeout(() => {
throw new Error("Whoops!");
}, 1000);
})
.catch(error => {
console.log('catch error:', error);
});
//无任何输出
解决executor 中的异步错误:resolve
/reject
,便于后续链式调用
new Promise((resolve, reject) => {
setTimeout(() => {
try {
resolve()
} catch(error) {
reject(error)
}
}, 1000);
})
try…catch: promise 内部的错误不会冒泡
function fn1() {
try {
new Promise((resolve, reject) => {
throw new Error('promise1 error')
})
} catch (error) {
console.log(e.message);
}
}
function fn2() {
try {
Promise.reject('promise2 error');
} catch (error) {
console.log(error);
}
}
A.then、catch捕获
B.async/await
// 模拟请求
function http(params) {
return new Promise((resolve, reject) => {
setTimeout(() => {
if (params === 0) reject("error")
resolve("success")
}, 1000);
})
}
// 业务调用
async function query(params) {
try {
const data = await http(params)
console.log('data:', data);
} catch (error) {
console.log('error:', error);
}
}
query(0)
中断promise:return pending 的 promise
new Promise(() => {})
.catch((err) => {
console.log('onRejected', err);
// 中断promise链:
return new Promise(() => {})
})
fetch es6 api:基于promise,简单易用
window.fetch(url, { method: 'get'}) //fetch() 返回响应的promise
// 第一个then 设置请求的格式
.then(res => return res.json()) // 第一层then返回的是:响应的报文对象
.then((data) => { //第二层:如果想要使用第一层的数据,必须把数据序列化
res.json() 返回的对象是一个 Promise对象再进行then()
<!-- data为真正数据 -->
}).catch(e => console.log("Oops, error", e))
回调函数:参数为函数,且满足条件才执行该参数函数
隐式return 原promise对象/ 显式return (非promise会包装成promise)
then/catch/finally/async
async/await函数
Promise.resolve(a)
.then(b => {
// do something
})
.then(c => {
// do something
})
//等价于
async () => {
const a = await Promise.resolve(a);
const b = await Promise.resolve(b);
const c = await Promise.resolve(c);
}
async
关键字+函数
await 操作符+promise对象
promise对象变成reject状态时,整个async函数会中断
处理异常: try-catch 块
async function asyncFunc() {
try {
await new Promise(function (resolve, reject) {
throw "Some error"; // 或者 reject("Some error")
});
} catch (err) {
console.log(err);
// 会输出 Some error
}
}
asyncFunc();