Promise 的执行顺序分析
Promise 对象的执行是异步的,但其执行器函数内部的代码是立即执行的,而 then方法注册的回调函数则是在 Promise 状态改变后执行的。
const myPromise = new Promise((resolve, reject) => {
console.log('A');
console.log('B');
});
myPromise.then(() => {
console.log('C');
});
console.log('D');
A-》B-》D
const newPromise1 = new Promise((resolve, reject) => {
console.log('A');
resolve('B');
});
const newPromise2 = newPromise1.then(res => {
console.log(res);
});
console.log('C', newPromise1);
console.log('D', newPromise2);
A-》C Promise{<fulfilled>:'B'}->D Promise{<pending>}->B
const newPromise = new Promise((resolve, reject) => {
console.log('A');
setTimeout(() => {
console.log("timer start");
resolve("succeed");
console.log("timer end");
}, 0);
console.log('B');
});
newPromise.then((result) => {
console.log(result);
});
console.log('C');
事件循环
A-》B-》C-》timer starter->timer end ->succeed
流程解读
- 当执行到
new Promise
时,会立即执行Promise构造函数中的执行器函数(executor function),即传递给Promise
构造函数的箭头函数。- 在执行器函数内部,首先打印出
'A'
。- 然后,
setTimeout
被调用,它设置了一个延时为0毫秒的定时器回调。由于setTimeout
的回调被放入了宏任务队列(macrotask queue),它不会立即执行,而是等待当前执行栈清空并且微任务队列(microtask queue)也为空时,才会被执行。- 紧接着,打印出
'B'
。- 此时,Promise的执行器函数执行完毕,但Promise对象
newPromise
的状态仍然是pending,因为resolve
函数是在setTimeout
的回调中调用的,而这个回调还没有执行。- 紧接着,打印出
'C'
。- 事件循环和微任务队列:到目前为止,执行栈已经清空,继续执行微任务队列、宏任务队列中的任务,执行setTimeout()内回调函数。
- resolve方法会触发在微异步任务队列then()方法,因此先输出栈中数据timer end,再检查队列中待执行的任务resolve
事件循环(Event Loop):事件循环是JavaScript运行时环境中的一个循环机制,它不断地检查调栈用和任务队列。当调用栈为空时,事件循环会首先检查微任务队列,并执行其中的所有任务。只有当微任务队列为空时,事件循环才会检查任务队列,并执行其中的任务。(调用栈-》微任务队列-》宏任务队列)
- 微任务队列:它专门用于处理如
Promise
的resolve
或reject
回调、async/await
等微任务。微任务的优先级高于宏任务。- 宏任务队列:用来存储准备好执行的回调函数,比如
setTimeout
和setInterval
的回调- 调用栈
Promise.resolve().then(() => {
console.log('outerPromise');
const innerTimer = setTimeout(() => {
console.log('innerTimer')
}, 0)
});
const timer1 = setTimeout(() => {
console.log('outerTimer')
Promise.resolve().then(() => {
console.log('innerPromise')
})
}, 0)
console.log('run');
run-》outerPromise-》outerTimer-》innerPromise-》innerTimer
then方法里面的return语句讲状态改为fulfilled!
Promise.resolve().then(() => {
return new Error('error')
}).then(res => {
console.log("then: ", res)
}).catch(err => {
console.log("catch: ", err)
})
//打印出then: Error: error
TypeError: Chaining cycle detected for promise
const promise = Promise.resolve().then(() => {
return promise;
})
promise.catch(console.err)
//输出TypeError: Chaining cycle detected for promise
promise异常处理
.catch(err=>{console.log(err)}) | .then(res)=>{console.log(res)},(err)=>{console.log(err)}
两个都可以用于处理,那个在先就先处理错误!!!!
Promise.reject('error')
.then((res) => {
console.log('succeed', res)
}, (err) => {
console.log('innerError', err)
}).catch(err => {
console.log('catch', err)
})
innerError error
Promise.reject('error')
:创建一个被拒绝的Promise
,拒绝原因为'error'
。
.then((res) => { console.log('succeed', res) }, (err) => { console.log('innerError', err) })
:
- 第一个回调函数(处理成功情况的)不会被调用,因为这个
Promise
已经被拒绝。- 第二个回调函数(处理拒绝情况的)会被调用,因为它专门用于处理
Promise
被拒绝的情况。因此,会执行console.log('innerError', err)
,其中err
的值为'error'
。
.catch(err => { console.log('catch', err) })
:
.catch()
方法是.then(null, rejectionHandler)
的语法糖,专门用于捕获Promise
链中未被处理的拒绝情况。- 然而,在这个例子中,
.then()
方法已经包含了一个处理拒绝的回调函数,因此.catch()
方法不会被调用。
console.log('catch', err)
也不会被执行,.then()
方法中已经包含了处理拒绝的逻辑。
promise .finally()用法
被解决(fulfilled)或拒绝(rejected)之后,执行一些不依赖于
Promise
结果的代码。这个方法返回在JavaScript中,Promise.finally()
方法是一个非常有用的工具,它允许你在一个Promise
对象一个新的Promise
,该Promise
的解决值(fulfilled value)或拒绝原因(rejection reason)与原始Promise
相同。let promise = new Promise((resolve, reject) => { // 模拟一个异步操作 setTimeout(() => { resolve('操作成功'); // 如果改为 reject('操作失败'); 则会触发 catch 回调 }, 1000); }); promise .then(result => { console.log(result); // 操作成功 }) .catch(error => { console.error(error); // 如果Promise被拒绝,则会打印错误信息 }) .finally(() => { console.log('清理资源或执行其他不依赖于结果的代码'); // 这里可以执行一些清理工作,比如关闭数据库连接、清除缓存等 });
Promise.resolve('A')
.then(res => {
console.log('promise1', res)
})
.finally(() => {
console.log('finally1')
})
Promise.resolve('B')
.finally(() => {
console.log('finally2')
return 'result'
})
.then(res => {
console.log('promise2', res)
})
//打印promise1 A、finally1、finally2、promise2 B
promise.all()方法
Promise.all()
是 JavaScript 中一个非常有用的方法,它接受一个包含多个Promise
对象(或可迭代对象,如数组)的可迭代对象,并返回一个新的Promise
。这个新的Promise
会在所有给定的Promise
对象都成功解决(fulfilled)后解决,其解决值(fulfilled value)是一个数组,包含了所有原始Promise
对象的解决值(按相同的顺序)。如果任何一个Promise
对象被拒绝(rejected),则新的Promise
会立即被拒绝,其拒绝原因(rejection reason)是第一个被拒绝的Promise
的拒绝原因。
Promise.all([promise1, promise2, promise3])
.then((values) => {
// 所有 Promise 都成功解决后执行这里的代码
// “!!!values 是一个数组”,包含了 promise1, promise2, promise3 的解决值
})
.catch((error) => {
// 如果有任何一个 Promise 被拒绝,则执行这里的代码
// error 是第一个被拒绝的 Promise 的拒绝原因
});
function runAsync(num) {
return new Promise((resolve) => setTimeout(
() => resolve(num, console.log(num)), 1000)
);
}
function runReject(num) {
return new Promise((resolve, reject) => setTimeout(
() => reject(`Error: ${num}`, console.log(num)), 1000 * num)
);
}
Promise.all([runAsync(1), runReject(4), runAsync(3), runReject(2)])
.then((res) => console.log(res))
.catch((err) => console.log(err));
- 1s后 runAsync(1)、runAsync(3)输出1、3
- 2s号 runReject(2)输出2,状态为reject,promise.all()捕获错误,执行.catch() Error 2
- 4s后runAsync(4)输出4
标签:resolve,console,log,err,res,选择题,JS,Promise,分析题 From: https://blog.csdn.net/m0_55049655/article/details/143643577