#### 1. Promise 的执行顺序与事件循环
题目:以下代码的输出顺序是什么?
javascript
console.log('start');
const promise = new Promise(resolve => {
console.log(1);
resolve();
console.log(2);
});
promise.then(() => console.log(3));
console.log('end');
答案:
sql
start → 1 → 2 → end → 3
解析:
new Promise
构造函数内的代码是同步执行 的,输出1
和2
;then
的回调是微任务 ,在同步代码执行完毕后触发,输出3
;- 事件循环顺序:同步代码 → 微任务 → 宏任务。
#### 2. Promise 状态不可变性
题目:以下代码的输出是什么?
javascript
const promise = new Promise((resolve, reject) => {
resolve('success1');
reject('error');
resolve('success2');
});
promise.then(res => console.log(res)).catch(err => console.log(err));
答案:
success1
解析:
- Promise 状态一旦变为
resolved
或rejected
,后续调用resolve
/reject
无效; - 只有第一次
resolve('success1')
生效。
3. then
方法的参数处理
题目:以下代码的输出是什么?
scss
Promise.resolve(1)
.then(2)
.then(Promise.resolve(3))
.then(console.log);
答案:
1
解析:
then
方法的参数必须是函数 ,否则会被忽略(如then(2)
和then(Promise.resolve(3))
);- 只有最后一个
then
接收函数,输出1
。
#### 4. 链式调用与值传递
题目:以下代码的输出是什么?
javascript
Promise.resolve(1)
.then(res => res + 1)
.then(res => { throw new Error('error') })
.then(res => console.log(res))
.catch(err => console.log(err.message));
答案:
go
error
解析:
- 链式调用中,
then
返回的值会传递给下一个then
; - 如果某一步抛出错误,后续
then
被跳过,直接触发catch
。
5. Promise.resolve
的静态方法
题目:以下代码的输出是什么?
ini
const p1 = Promise.resolve(Promise.resolve(1));
const p2 = Promise.resolve(2);
p1.then(console.log);
p2.then(console.log);
答案:
1 → 2
解析:
Promise.resolve
的参数如果是 Promise,会直接返回该 Promise;p1
和p2
都解析为普通值,按微任务队列顺序输出。
1. Promise.all
与 Promise.allSettled
的区别
题目 :如何实现一个函数,无论 Promise 成功或失败都返回结果?
答案:
- **
Promise.allSettled
**:
ini
Promise.allSettled([promise1, promise2])
.then(results => results.forEach(result => console.log(result.status)));
- 无论单个 Promise 成功/失败,都会返回所有结果56;
- 与
Promise.all
的区别:all
在任意一个 Promise 失败时立即终止。
2. async/await
与 Promise 的关系
题目:以下代码的输出顺序是什么?
javascript
async function foo() {
console.log(1);
await Promise.resolve().then(() => console.log(2));
console.log(3);
}
console.log(4);
foo();
console.log(5);
答案:
4 → 1 → 5 → 2 → 3
解析:
async
函数内的await
会暂停后续代码执行,将其后的代码包装为微任务;- 执行顺序:同步代码 → 微任务(
then
和await
后的代码)。
#### 3. 微任务队列与事件循环
题目:以下代码的输出顺序是什么?
scss
setTimeout(() => console.log(1), 0);
Promise.resolve().then(() => console.log(2));
queueMicrotask(() => console.log(3));
console.log(4);
答案:
4 → 2 → 3 → 1
解析:
- 微任务(
then
和queueMicrotask
)优先于宏任务(setTimeout
)执行; - 微任务队列按注册顺序执行。
**4. 手写 Promise.all
**
题目 :实现一个 Promise.all
的简化版本。
答案:
ini
function promiseAll(promises) {
return new Promise((resolve, reject) => {
const results = [];
let count = 0;
promises.forEach((promise, index) => {
Promise.resolve(promise)
.then(res => {
results[index] = res;
if (++count === promises.length) resolve(results);
})
.catch(reject);
});
});
}
要点:
- 处理非 Promise 值(
Promise.resolve(promise)
); - 计数完成数量,全部成功则返回结果数组。
#### 5. Promise 的错误处理策略
题目:以下两种错误处理方式有何区别?
dart
// 方式1
promise.then(res => {}, err => {});
// 方式2
promise.then(res => {}).catch(err => {});
答案*:*
- 方式1 :
then
的第二个参数只能捕获当前 Promise 的直接错误; - 方式2 :
catch
可以捕获链式调用中所有前置步骤的错误; - 最佳实践:优先使用
catch
统一处理错误。
复制一个vue页面在新的窗口打开经历了那些生命周期
当通过 window.open()
或浏览器手动复制页面到新窗口时,新窗口的 Vue 实例会重新初始化,完整经历以下生命周期阶段:
一、核心生命周期阶段
-
创建阶段
- **
beforeCreate
**:实例初始化后,数据观测和事件配置前触发。 - **
created
**:数据观测、计算属性、方法等初始化完成,但 DOM 未生成。
- **
-
挂载阶段
- **
beforeMount
**:模板编译完成,虚拟 DOM 已生成但未挂载到真实 DOM。 - **
mounted
**:实例挂载到新窗口的 DOM 树中,可操作 DOM 元素。
- **
二、流程细节与注意事项
-
独立实例
新窗口的 Vue 实例与原页面完全独立,不会共享响应式数据或状态。
-
不触发的钩子
- 更新阶段 (
beforeUpdate
/updated
):仅在数据变化导致重新渲染时触发,初始化时不触发。 - 销毁阶段 (
beforeUnmount
/unmounted
):仅当新窗口关闭或实例手动销毁时触发。
- 更新阶段 (
-
路由影响
若页面包含 Vue Router,新窗口会重新执行路由匹配和组件加载流程,可能触发路由守卫(如
beforeRouteEnter
)。
总结
复制到新窗口的 Vue 页面会依次执行:
**beforeCreate
→ created
→ beforeMount
→ mounted
**,完成数据初始化和 DOM 挂载。
若新窗口操作数据或关闭窗口,则可能触发更新或销毁阶段的钩子。