「寒冬」三年經驗前端面試總結(含頭條、百度、餓了麼、滴滴等)之手寫題(promise篇)

前言

不管是寒冬仍是暖冬,找工做以前都須要作好充足的準備,面試的時候才能作到遊刃有餘。此文是把我最近找工做準備的以及筆試面試中涉及到的手寫題作一個總結。給本身,也給須要的同窗。 手寫題是比較好準備的一個環節,大部分公司考察的題也就那麼多,大都不會超出範圍。前端

本篇主要涉及promise相關的題目。


往期:

  1. 「寒冬」三年經驗前端面試總結(含頭條、百度、餓了麼、滴滴等)
  2. 「寒冬」三年經驗前端面試總結(含頭條、百度、餓了麼、滴滴等)之CSS篇
  3. 「寒冬」三年經驗前端面試總結(含頭條、百度、餓了麼、滴滴等)之手寫題(一)
  4. 「寒冬」三年經驗前端面試總結(含頭條、百度、餓了麼、滴滴等)之手寫題(二)

實現一個sleep函數

sleep 函數的做用就是延遲指定時間後再執行接下來的函數。用 promise 很好實現。node

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)
      })
  })}
複製代碼

按照上面的思路,便可寫出通用版的形式。promise

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 個的部分按調用順序進行排隊,當前一個請求完成時,再發送隊列中的下一個請求。bash

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();
        })
    }
}
複製代碼

寫在最後

有錯誤之處還請小夥伴們及時指出,以避免誤人子弟。想看往期內容,翻到頁面最上面有連接~微信

相關文章
相關標籤/搜索