做网站送优化,网站 哪些服务器,建网站卖饮料,网站开发一键上架淘宝前端面试题库 #xff08;面试必备#xff09; 推荐#xff1a;★★★★★
地址#xff1a;前端面试题库 表妹一键制作自己的五星红旗国庆头像#xff0c;超好看 在学习Promise相关题目之前#xff0c;我们先做一些知识的回顾#xff1a;JavaScript 是一门单… 前端面试题库 面试必备 推荐★★★★★
地址前端面试题库 表妹一键制作自己的五星红旗国庆头像超好看 在学习Promise相关题目之前我们先做一些知识的回顾JavaScript 是一门单线程执行的编程语言。也就是说同一时间只能做一件事情。 JS执行机制中有同步任务和异步任务执行入队优先级是前者异步任务又分为宏任务和微任务执行入队优先级是后者。我们先看一下下面例子来充分理解一下JavaScript执行机制如代码所示。如图所示
console.log(1)
setTimeout(() {console.log(2)
}, 0)
const promise new Promise((resolve, reject) {console.log(3);resolve(4)
})
promise.then((res) {console.log(res)
})
// 1 3 4 2同步任务只有前一个任务执行完毕才能执行后一个任务。还记得大学饭堂排队打饭例子吗作为一个优秀的当代大学生排队打饭遵循先来先打后来排队原则只有前面那一个同学打完饭你才能打。当然你插队就另说。异步任务由JavaScript 委托给宿主环境进行执行。当异步任务执行完成后会通知JavaScript 主线程执行异步任务的回调函数。还记得铁板烧吗说实际的铁板烧确实不错细心的你有没有发现老板里有多个锅不可能只有一个锅每一份铁板烧都需要时间不然让顾客等待得花儿都谢了你下次也不会来了所以多个锅就代表多个任务不需要等待一个锅烧完才去重新烧也就是说不需要等待当前任务结束这个任务没有那么快完成未来某个时间点才结束它就是异步任务为节省时间或能耗可以继续去执行其他任务。宏任务JavaScript自身发起。如setTimeout 、setInterval MessageChannel I/O、setImmediateNode环境、script整体代码块微任务是由宿主浏览器、Node发起的。MutationObserver浏览器环境、promise.[ then/catch/finally ]、事件队列 process.nextTickNode环境Promise异步编程的一种解决方案可以通俗把它当作一个容器内部存储着某个未来才会结束的事件通常是一个异步操作的结果从语法上来讲它就是一个对象有两个特点 有三种状态pending进行中、fulfilled已成功和rejected已失败 对象状态不受外界影响。状态一旦改变就不会在变也就是说任何时候Promise都只有一种状态。
话不多说我们直接上题目实操吧一步步理解
题目1️⃣Promise没有resolve前都是同步任务。 Promise是微任务但是Promise构造器内有同步任务js线程会先把同步任务执行完再去执行resolve回调。
const promise new Promise((resolve, reject) {console.log(1);resolve(2)console.log(3);
});
promise.then((res) {console.log(res);
});
console.log(4, promise);// 4 fulfilled
// 1 3 4 2题目2️⃣当函数返回的是一个Promise实例。
const fn () (new Promise((resolve, reject) {console.log(1);resolve(2)
}))
fn().then(res {console.log(res)
})
console.log(3)
// 1 3 2题目3️⃣宏任务与微任务执行顺序。 定时器是宏任务Promise是微任务其他都是同步任务
console.log(1)
setTimeout(() {console.log(2)
})
Promise.resolve().then(() {console.log(3)
})
console.log(4)
// 1 4 3 2题目4️⃣当微任务中嵌套宏任务、宏任务嵌套微任务、宏任务嵌套宏任务、微任务嵌套微任务时。 当微任务中嵌套宏任务时由于构造器中除了resolve执行回调之外还有其他同步任务、宏任务。 // 当微任务中嵌套宏任务
const promise new Promise((resolve, reject) {console.log(1);setTimeout(() {console.log(2);resolve(3);console.log(4);}, 0);console.log(5);
});
promise.then((res) {console.log(res);
});
console.log(6);
// 1 5 6 2 4 3当宏任务嵌套宏任务时当发生嵌套任务时优先处理同层级因为程序是自上而下的setTimeout是异步任务中的宏任务同层级的比嵌套的先入队所以先执行同层级。 // 宏任务嵌套宏任务
setTimeout(() {console.log(1);setTimeout(() {console.log(2)}, 0)
}, 0)
setTimeout(() {console.log(3)
}, 0)
console.log(4)
// 4 1 3 2当宏任务嵌套微任务时 // 宏任务嵌套微任务
setTimeout(() {console.log(1);// 微任务Promise.resolve().then(() {console.log(2)})
}, 0)
setTimeout(() {console.log(3)
}, 0)
console.log(4)
// 4 1 2 3微任务嵌套微任务时同层级微任务优先执行。因为任务队列先入队都是同级别的。 // 微任务链接微任务
Promise.resolve().then(() {console.log(1)return 2;
}).then((res) {console.log(res);
})
Promise.resolve().then(() {console.log(3)
})
// 1 3 2// 微任务嵌套微任务
Promise.resolve().then(() {console.log(1)Promise.resolve().then(() {console.log(2)})return 3
}).then((res) {console.log(res);
})
Promise.resolve().then(() {console.log(4)
})
// 1 4 2 3题目5️⃣结合微任务和宏任务灵活理解Promise三种状态。从代码中我们可以看出例子中的单纯是同步任务有2 3 4而宏任务中的同步任务是1当执行程序中同步任务时微任务还没有resolve回调函数所以promise对象都是pending状态由于抛出错误是微任务中的宏任务所以优先执行然后再执行全局的setTimeout最后promise1是fufilled状态promise2是rejected状态。
const promise1 new Promise((resolve, reject) {setTimeout(() {resolve(success);console.log(1);}, 1000);console.log(2);
});
const promise2 promise1.then(() {throw new Error(error!!!);
});
console.log(3, promise1);// pending
console.log(4, promise2);// pending
setTimeout(() {console.log(5);console.log(6, promise1);// fufilledconsole.log(7, promise2);// rejected
}, 2000);
// 2 3 4 1 抛出error! 5 6 7题目6️⃣Promise中构造函数中的resolve或reject只有第一次执行有效。
const promise new Promise((resolve, reject) {resolve(1);reject(error);resolve(2);
});
promise.then(res {console.log(then: , res);
}).catch(err {console.log(catch: , err);
})
// then1题目7️⃣Promise对象中的catch无视链接位置都能捕获上层未捕捉过的错误then3会执行因为catch会返回一个Promise且由于这个Promise没有返回值所以打印出来的是undefined。
const promise new Promise((resolve, reject) {reject(error);resolve(1);
});
promise.then(res {console.log(then1: , res);
}).then(res {console.log(then2: , res);
}).catch(err {console.log(catch: , err);
}).then(res {console.log(then3: , res);
})
// catch: error
// then3: undefined题目8️⃣Promise对象的链式调用的执行顺序。Promise可以链式调用不过promise 每次调用 .then 或者 .catch 都会返回一个新的 promise从而实现了链式调用,return 2会被包装为resolve(2)。
Promise.resolve(1)
.then(res {console.log(res);return 2;
})
.catch(err {return 3;
})
.then(res {console.log(res);
});
// 1 2题目9️⃣注意then的第二参数错误处理与catch的区别。两个都是处理reject状态回调结果或者是抛出的错误如果存在第二参数也存在catch捕获错误是参数生效否则就会catch生效。也可以这样理解then的第一个参数是处理成功的函数第二个参数是处理失败的函数。如果两个都没有就会直接报错。
Promise.reject(err!!!).then((res) {console.log(success, res)}, (err) {console.log(error, err)}).catch(err {console.log(catch, err)})
// error err!!!Promise.resolve()
.then(() {throw new Error(error!!!);
})
.then(function success(res) {},function fail1(err) {console.log(fail1, err);}
)
.catch(function fail2(err) {console.log(fail2, err);
});
// fail1 Error: error!!!题目then参数是函数对于非函数会出现值穿透。 如果then传入的是非函数resolve会被传到是函数的地方。
Promise.resolve(1).then(2).then(Promise.resolve(3))
.then(console.log)
// 1题目1️⃣1️⃣finally方法也是一个微任务。.finally()方法不管Promise对象最后的状态如何都会执行。.finally()方法的回调函数不接受任何的参数。
function promise1() {let p new Promise((resolve) {console.log(1);resolve(2)})return p;
}
function promise2() {return new Promise((resolve, reject) {reject(error)})
}
promise1().then(res console.log(res)).catch(err console.log(err)).finally(() console.log(finally1))promise2().then(res console.log(res)).catch(err console.log(err)).finally(() console.log(finally2))
// 1 2 error finally1 finally2题目1️⃣2️⃣async await执行机制在async1中await后面的Promise是没有返回值的也就是它的状态始终是pending状态因此相当于一直在awaitawaitawait却始终没有响应所以就不能执行await后面的语句了。 async await宏任务await强制的是当前async函数域所以不能优先处理await后面的语句全局同步任务可优先处理。 async function async1() {console.log(1);await async2();console.log(2);
}
async function async2() {setTimeout(() {console.log(3)}, 0)console.log(4);
}
async1();
console.log(5)
// 1 4 5 2 3async await微任务 async function async1() {console.log(1);await new Promise(resolve {console.log(2)})// Promise没有resolve所以一直处于pendingconsole.log(3);return async1 end
}
console.log(4)
async1().then(res console.log(res))
console.log(5)
// 4 1 2 5async await微任务、宏任务 async function testSometing() {console.log(1);return 2;
}
async function testAsync() {console.log(3);return Promise.resolve(4);
}
async function test() {console.log(5);const v1 await testSometing();console.log(v1);const v2 await testAsync();console.log(v2);console.log(v1, v2);
}
test();
var promise new Promise(resolve {console.log(6);resolve(7);
});
promise.then(val console.log(val));
console.log(8);
// 5 1 6 8 2 3 7 4
// 2 4题目1️⃣3️⃣理解Promise.all方法all方需要等所有异步操作执行完后才执行回调由于有reject状态的回调所以没有执行then直接执行了catch。
function runAsync(x) {const p new Promise(r setTimeout(() r(x, console.log(runAsync, x)), 1000))return p
}
function runReject(x) {const p new Promise((res, rej) setTimeout(() rej(Error: ${x}, console.log(runRejct, x)), 1000 * x))return p
}
Promise.all([runAsync(1), runReject(4), runAsync(3), runReject(2)]).then(res console.log(then:, res)).catch(err console.log(catch:, err))
// runAsync 1
// runAsync 3
// runRejct 2
// catch: Error: 2
// runRejct 4问题1️⃣4️⃣理解Promise.race方法race获取最快的哪一个异步操作的结果。由于下面执行了一个reject状态的回调所以没有执行then如果没有这个runReject(0)下面例子打印的是1 result:1 2 3。
function runAsync(x) {
const p new Promise(r setTimeout(() r(x, console.log(x)), 1000)
);
return p;
}
function runReject(x) {
const p new Promise((res, rej) setTimeout(() rej(Error: ${x}, console.log(x)), 1000 * x)
);
return p;
}
Promise.race([runReject(0), runAsync(1), runAsync(2), runAsync(3)])
.then(res console.log(result: , res))
.catch(err console.log(err));
// 0 Error:0 1 2 3问题1️⃣5️⃣ 构造函数里resolve之前的同步任务打印3 7优先执行然后就是first后面的全局同步任务4注意这里与上面的嵌套微任务的区别因为这里直接resolve(2)的话first就会完成回调函数了但是最外层构造函数内还有一个微任务p所以先执行。
const first () (new Promise((resolve, reject) {console.log(3);let p new Promise((resolve, reject) {console.log(7);setTimeout(() {console.log(5);resolve(6);console.log(p)}, 0)resolve(1);});resolve(2);p.then((arg) {console.log(arg);});
}));
first().then((arg) {console.log(arg);
});
console.log(4);
// 3 7 4 1 2 5 fulfilled:1问题1️⃣6️⃣综合Promise值穿透、宏任务、微任务、async await
const async1 async () {console.log(1);setTimeout(() {console.log(2)}, 2000)await new Promise(resolve {console.log(3)})console.log(4)return 5
}
console.log(6);
async1().then(res console.log(res));
console.log(7);
Promise.resolve(8).then(9).then(Promise.resolve(10)).catch(11).then(res console.log(res))
setTimeout(() {console.log(12)
}, 1000)
//6 1 3 7 8 12 2问题1️⃣7️⃣ Promise的状态一旦改变就无法改变。.finally的返回值如果在没有抛出错误的情况下默认会是上一个Promise的返回值。由于微任务Promise中有宏任务并且有多个resolve但是Promise值只能回调一个函数所以打印了3.finally也是一个微任务并且不接收回调函数参数所以为undefined然后执行微任务Promise中宏任务接着执行then中的宏任务此时p1状态是undefined没有then处理。
const p1 new Promise((resolve) {setTimeout(() {resolve(1);console.log(2)}, 0)resolve(3);resolve(4);
}).then(res {console.log(res)// 打印3setTimeout(() {console.log(p1)}, 1000)
}).finally(res {console.log(finally:, res)
})
// 3 finally:undefined 2 fulfilled:undefined✍总结其实学完这17道题目希望各位同仁有收获对于Promise的执行有更深理解与掌握。接下来就总结一下如何快速处理这种题目的技巧从上到下按顺序理解 先看是否同步任务对于非函数先看当前语句是否是同步任务是就先执行对于函数不管是同步还是异步操作也是先执行同步任务。 异步任务判断是宏任务还是为微任务先执行微任务后执行宏任务。 任务嵌套情况灵活处理不管是微任务还是宏任务先处理同级别任务但是对于微任务有些情况特殊需要灵活理解。 Promise特点要重视 对象状态不受外界影响状态一旦改变就不会再变。then传参必须是函数否则出现值穿透。理解catch处理与then第二个参数处理。Promise如果没有resolve或reject就会一直处于pending状态。区分all方法与race方法。 理解async await强制执行函数体内await当前语句完毕也相当于一个微任务才会执行函数体内await后面的语句。 前端面试题库 面试必备 推荐★★★★★
地址前端面试题库 表妹一键制作自己的五星红旗国庆头像超好看