前言
不論是寒冬還是暖冬,找工作之前都需要做好充足的準備,面試的時候才能做到遊刃有餘。此文是把我最近找工作準備的以及筆試面試中涉及到的手寫題做一個總結。給自己,也給需要的同學。
手寫題是比較好準備的一個環節,大部分公司考察的題也就那麼多,大都不會超出範圍。
本篇主要涉及promise相關的題目。
往期:
- "寒冬"三年經驗前端面試總結(含頭條、百度、餓了麼、滴滴等)
- "寒冬"三年經驗前端面試總結(含頭條、百度、餓了麼、滴滴等)之手寫題(一)
- "寒冬"三年經驗前端面試總結(含頭條、百度、餓了麼、滴滴等)之手寫題(二)
實現一個sleep函數
sleep 函數的作用就是延遲指定時間後再執行接下來的函數。用 promise 很好實現。
function sleep(time) {
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve(true);
}, time*1000);
});
}
實現Promise.all
Promise.all 需要等到所有的 promise 的狀態都變成 fulfilled 之後才 resolve, 但只要有一個 promise 失敗即返回失敗的結果。
Promise.all = function(arr){
return new Promise((resolve,reject) => {
if(!Array.isArray(arr)){
throw new TypeError(`argument must be a array`)
}
var length = arr.length;
var resolveNum = 0;
var resolveResult = [];
for(let i = 0; i < length; i++){
arr[i].then(data => {
resolveNum++;
resolveResult.push(data)
if(resolveNum == length){
return resolve(resolveResult)
}
}).catch(data => {
return reject(data)
})
}
})
}
promise.retry
promise.retry 的作用是執行一個函數,如果不成功最多可以嘗試 times 次。傳參需要三個變量,所要執行的函數,嘗試的次數以及延遲的時間。
Promise.retry = function(fn, times, delay) {
return new Promise(function(resolve, reject){
var error;
var attempt = function() {
if (times == 0) {
reject(error);
} else {
fn().then(resolve)
.catch(function(e){
times--;
error = e;
setTimeout(function(){attempt()}, delay);
});
}
};
attempt();
});
};
將一個同步callback包裝成promise形式
同步的 callback 用的最多的是在 node 的回調中,例如下面這種,包裝完之後就可以愉快的使用 .then 了。
nodeGet(param, function (err, data) { })
// 轉化成promise形式
function nodeGetAysnc(param) {
return new Promise((resolve, reject) => {
nodeGet(param, function (err, data) {
if (err !== null) return reject(err)
resolve(data)
})
})}
按照上面的思路,即可寫出通用版的形式。
function promisify(fn,context){
return (...args) => {
return new Promise((resolve,reject) => {
fn.apply(context,[...args,(err,res) => {
return err ? reject(err) : resolve(res)
}])
})
}
}
寫一個函數,可以控制最大併發數
微信小程序最一開始對併發數限制為5個,後來升級到10個,如果超過10個會被捨棄。後來微信小程序升級為不限制併發請求,但超過10個會排隊機制。也就是當同時調用的請求超過 10 個時,小程序會先發起 10 個併發請求,超過 10 個的部分按調用順序進行排隊,當前一個請求完成時,再發送隊列中的下一個請求。
function concurrentPoll(){
this.tasks = [];
this.max = 10;
setTimeout(() => {
this.run()
},0)
}
concurrentPoll.prototype.addTask = function(task){
this.tasks.push(task)
}
concurrentPoll.prototype.run = function(){
if(this.tasks.length == 0){
return
}
var min = Math.min(this.tasks.length, max);
for(var i = 0; i < min; i++){
this.max--;
var task = this.tasks.shift();
task().then((res) => {
console.log(res)
}).catch((err) => {
console.log(err)
}).finally(() => {
this.max++;
this.run();
})
}
}
寫在最後
有錯誤之處還請小夥伴們及時指出,以免誤人子弟。想看往期內容,翻到頁面最上面有鏈接~