其实前端开发的知识点就那么多,面试问来问去还是那么点东西。所以面试没有其他的诀窍,只看你对这些知识点准备的充分程度。so,出去面试时先看看自己复习到了哪个阶段就好。
这里再分享一个复习的路线:(以下体系的复习资料是我从各路大佬收集整理好的)
开源分享:【大厂前端面试题解析+核心总结学习笔记+真实项目实战+最新讲解视频】
《前端开发四大模块核心知识笔记》
最后,说个题外话,我在一线互联网企业工作十余年里,指导过不少同行后辈。帮助很多人得到了学习和成长。
我意识到有很多经验和知识值得分享给大家,也可以通过我们的能力和经验解答大家在IT学习中的很多困惑,所以在工作繁忙的情况下还是坚持各种整理和分享。
.then((res) => {
console.log(res)
return 2
})
.catch((err) => {
return 3
})
.then((res) => {
console.log(res)
})
解析:
promise 可以链式调用。提起链式调用我们通常会想到通过 return this 实现,不过 Promise 并不是这样实现的。promise 每次调用 .then 或者 .catch 都会返回一个新的 promise,从而实现了链式调用。
运行结果:
1
2
06
const promise = new Promise((resolve, reject) => {
setTimeout(() => {
console.log(‘once’)
resolve(‘success’)
}, 1000)
})
const start = Date.now()
promise.then((res) => {
console.log(res, Date.now() - start)
})
promise.then((res) => {
console.log(res, Date.now() - start)
})
解析:
promise 的 .then 或者 .catch 可以被调用多次,但这里 Promise 构造函数只执行一次。或者说 promise 内部状态一经改变,并且有了一个值,那么后续每次调用 .then 或者 .catch 都会直接拿到该值。
运行结果:
once
success 1005
success 1007
07
Promise.resolve()
.then(() => {
return new Error(‘error!!!’)
})
.then((res) => {
console.log('then: ', res)
})
.catch((err) => {
console.log('catch: ', err)
})
解析:
.then 或者 .catch 中 return 一个 error 对象并不会抛出错误,所以不会被后续的 .catch 捕获,需要改成其中一种:
return Promise.reject(new Error(‘error!!!’))
throw new Error(‘error!!!’)
因为返回任意一个非 promise 的值都会被包裹成 promise 对象,即 return new Error(‘error!!!’) 等价于 return Promise.resolve(new Error(‘error!!!’))。
运行结果:
then: Error: error!!!
at
08
const promise = Promise.resolve()
.then(() => {
return promise
})
promise.catch(console.error)
解析:.then 或 .catch 返回的值不能是 promise 本身,否则会造成死循环。类似于:
process.nextTick(function tick () {
console.log(‘tick’)
process.nextTick(tick)
})
运行结果:
TypeError: Chaining cycle detected for promise #
09
Promise.resolve(1)
.then(2)
.then(Promise.resolve(3))
.then(console.log)
解析:
.then 或者 .catch 的参数期望是函数,传入非函数则会发生值穿透。
运行结果:
1
10
Promise.resolve()
.then(function success (res) {
throw new Error(‘error’)
}, function fail1 (e) {
console.error('fail1: ', e)
})
.catch(function fail2 (e) {
console.error('fail2: ', e)
})
解析:
.then 可以接收两个参数,第一个是处理成功的函数,第二个是处理错误的函数。
.catch 是 .then 第二个参数的简便写法,但是它们用法上有一点需要注意:.then 的第二个处理错误的函数捕获不了第一个处理成功的函数抛出的错误,而后续的 .catch 可以捕获之前的错误。
当然以下代码也可以:
Promise.resolve()
.then(function success1 (res) {
throw new Error(‘error’)
}, function fail1 (e) {
console.error('fail1: ', e)
})
.then(function success2 (res) {
}, function fail2 (e) {
console.error('fail2: ', e)
})
运行结果:
fail2: Error: error
at success ()
11
process.nextTick(() => {
console.log(‘nextTick’)
})
Promise.resolve()
.then(() => {
console.log(‘then’)
})
setImmediate(() => {
console.log(‘setImmediate’)
})
console.log(‘end’)
解析:
process.nextTick 和 promise.then 都属于 microtask,而 setImmediate 属于 macrotask,在事件循环的 check 阶段执行。事件循环的每个阶段(macrotask)之间都会执行 microtask,事件循环的开始会先执行一次 microtask。
运行结果:
end
nextTick
then
setImmediate
编程题
上面题目太基础,没有挑战性?那就来点有难度的!
12
红灯3秒亮一次,绿灯1秒亮一次,黄灯2秒亮一次;如何使用Promise让三个灯不断交替重复亮灯?(海康威视笔试题)
function red(){
console.log(‘red’);
}
function green(){
console.log(‘green’);
}
function yellow(){
console.log(‘yellow’);
}
分析:
先看题目,题目要求红灯亮过后,绿灯才能亮,绿灯亮过后,黄灯才能亮,黄灯亮过后,红灯才能亮……所以怎么通过Promise实现?
换句话说,就是红灯亮起时,承诺2s秒后亮绿灯,绿灯亮起时承诺1s后亮黄灯,黄灯亮起时,承诺3s后亮红灯……这显然是一个Promise链式调用,看到这里你心里或许就有思路了,我们需要将我们的每一个亮灯动作写在then()方法中,同时返回一个新的Promise,并将其状态由pending设置为fulfilled,允许下一盏灯亮起。
function red() {
console.log(‘red’);
}
function green() {
console.log(‘green’);
}
function yellow() {
console.log(‘yellow’);
}
let myLight = (timer, cb) => {
return new Promise((resolve) => {
setTimeout(() => {
cb();
resolve();
}, timer);
});
};
let myStep = () => {
Promise.resolve().then(() => {
return myLight(3000, red);
}).then(() => {
return myLight(2000, green);
}).then(()=>{
return myLight(1000, yellow);
}).then(()=>{
myStep();
})
};
myStep();
// output:
// => red
// => green
// => yellow
// => red
// => green
// => yellow
// => red
13
请实现一个mergePromise函数,把传进去的数组按顺序先后执行,并且把返回的数据先后放到数组data中。
const timeout = ms => new Promise((resolve, reject) => {
setTimeout(() => {
resolve();
}, ms);
});
const ajax1 = () => timeout(2000).then(() => {
console.log(‘1’);
return 1;
});
const ajax2 = () => timeout(1000).then(() => {
console.log(‘2’);
return 2;
});
const ajax3 = () => timeout(2000).then(() => {
console.log(‘3’);
return 3;
});
const mergePromise = ajaxArray => {
// 在这里实现你的代码
};
mergePromise([ajax1, ajax2, ajax3]).then(data => {
console.log(‘done’);
console.log(data); // data 为 [1, 2, 3]
});
// 要求分别输出
// 1
// 2
// 3
// done
// [1, 2, 3]
分析:
这道题主要考察用Promise控制异步流程,首先ajax1,ajax2,ajax3都是函数,只是这些函数执行后会返回一个Promise,按照题目要求只要顺序执行这三个函数就好了,然后把结果放到data中;
答案:
const mergePromise = ajaxArray => {
// 在这里实现你的代码
// 保存数组中的函数执行后的结果
var data = [];
// Promise.resolve方法调用时不带参数,直接返回一个resolved状态的 Promise 对象。
var sequence = Promise.resolve();
ajaxArray.forEach(item => {
// 第一次的 then 方法用来执行数组中的每个函数,
// 第二次的 then 方法接受数组中的函数执行后返回的结果,
// 并把结果添加到 data 中,然后把 data 返回。
sequence = sequence.then(item).then(res => {
data.push(res);
return data;
});
});
// 遍历结束后,返回一个 Promise,也就是 sequence, 他的 [[PromiseValue]] 值就是 data,
// 而 data(保存数组中的函数执行后的结果) 也会作为参数,传入下次调用的 then 方法中。
return sequence;
};
14
现有8个图片资源的url,已经存储在数组urls中,且已有一个函数function loading,输入一个url链接,返回一个Promise,该Promise在图片下载完成的时候resolve,下载失败则reject。
要求:任何时刻同时下载的链接数量不可以超过3个。
请写一段代码实现这个需求,要求尽可能快速地将所有图片下载完成。
var urls = [‘https://www.kkkk1000.com/images/getImgData/getImgDatadata.jpg’, ‘https://www.kkkk1000.com/images/getImgData/gray.gif’, ‘https://www.kkkk1000.com/images/getImgData/Particle.gif’, ‘https://www.kkkk1000.com/images/getImgData/arithmetic.png’, ‘https://www.kkkk1000.com/images/getImgData/arithmetic2.gif’, ‘https://www.kkkk1000.com/images/getImgData/getImgDataError.jpg’, ‘https://www.kkkk1000.com/images/getImgData/arithmetic.gif’, ‘https://www.kkkk1000.com/images/wxQrCode2.png’];
function loadImg(url) {
return new Promise((resolve, reject) => {
const img = new Image()
img.onload = () => {
console.log(‘一张图片加载完成’);
resolve();
}
img.onerror = reject;
img.src = url;
})
};
最后
好了,这就是整理的前端从入门到放弃的学习笔记,还有很多没有整理到,我也算是边学边去整理,后续还会慢慢完善,这些相信够你学一阵子了。
做程序员,做前端工程师,真的是一个学习就会有回报的职业,不看出身高低,不看学历强弱,只要你的技术达到应有的水准,就能够得到对应的回报。
开源分享:【大厂前端面试题解析+核心总结学习笔记+真实项目实战+最新讲解视频】
学习从来没有一蹴而就,都是持之以恒的,正所谓活到老学到老,真正懂得学习的人,才不会被这个时代的洪流所淘汰。