robbiemie/keep-learning

多多面试(day7)

Opened this issue · 1 comments

知识点

  1. ssr 渲染原理
  2. 补水(hydration)的过程
  3. ssr 返回的html片段,如何进行事件绑定

编程题

// 1. 将下面对象转换成新的结构
const entry = {
  a: {
    b: {
      c: {
        dd: "123"
      }
    }
  },
  d: {
    e: "234"
  },
  f: "345"
}

// output: { 'a.b.c.dd': '123', 'd.e': '234', f: '345' }

题解

function travel(obj) {
  function isObject(value) {
    return typeof value === 'object' && value !== null;
  }

  if(!isObject(obj)) return obj;

  const target= {};

  function clone(key, value, path = '') {
    const pathKey = path ? `${path}.${key}` : key;
    if(isObject(value)) {
      for(let k in value) {
        clone(k, value[k], pathKey)
      }
    } else {
      target[pathKey] = value;
    }
  }
  for(let key in obj) {
    clone(key, obj[key], '')
  }

  return target;
}


const output = travel(entry)
console.log(output);
  1. 实现如下函数
const res = lastSuccessPromise([
  new Promise(resolve => setTimeout(() => resolve(1), 200)),
  2,
  Promise.reject(new Error('something wrong'))
])

res.then(v => {
  console.log(v); // 1
})
function lastSuccessPromise(iterable) {
  if(!Array.isArray(iterable)) return Promise.reject(new Error('iterable is not a array type'));
  if(iterable.length === 0) return Promise.reject(new Error('iterable is empty'));

  let successQueue:Promise<number>[] = [];
  let failQueue:Promise<number>[] = [];
  let iterableTotal = iterable.length;

  return new Promise((resolve, reject) => {

    function handleFinally() {
      if(successQueue.length + failQueue.length === iterableTotal) {
        if(successQueue.length === 0) return reject(new Error('success is empty'));
        // 获取最后一个成功返回值
        resolve(successQueue.pop());
      }
    }

    function handlePromise(promise) {
      promise.then(res => {
        successQueue.push(res);
      }).catch(e => {
        failQueue.push(e);
      }).finally(e => {
        handleFinally()
      })
    }

    for(let item of iterable) {
      if(item instanceof Promise) {
        handlePromise(item);
      } else {
        successQueue.push(item);
      }
    }
    // 如果全是基础类型
    handleFinally();
  })
}

const res = lastSuccessPromise([
  new Promise(resolve => setTimeout(() => resolve(1), 200)),
  2,
  Promise.reject(new Error('something wrong'))
])

res.then(v => {
  console.log(v); // 1
})
  1. 实现一个 requestUrls 函数
/**
 * 入参: ['url1', 'url2', 'url3'];
 * 已知: url1、url2、url3 请求耗时分别是 200ms,100ms,300ms,结果返回值分别是 1,2,3
 * 请求执行后,返回的结果值分别是 200ms 后输出:1,2;300ms 后输出 3
 */

function requestUrls(urls) {
  if(urls.length === 0) return;
  let requestQueue:any[] = [];
  let curTaskIndex = 0;

  function checkTaskCompleted(index) {
    const tasks = requestQueue.slice(curTaskIndex, index);

    const i = tasks.indexOf(item => item instanceof Promise);
    if(i > -1) return;
    for(let res of tasks) {
      console.log(res);
    }
    curTaskIndex = index
  }

  function execTask() {
    for(let index in urls) {
      const promise = fetch(urls[index]);
      promise.then(res => {
        requestQueue.splice(+index, 1, res);
        checkTaskCompleted(index);
      })
      requestQueue.push(promise);
    }
  }

  execTask()

}
const urls = ['url1', 'url2', 'url3']
requestUrls(urls);

黑皮帅哥笔试题:

有这样的一个函数:

function asyncFn() {
  return new Promise((resolve, reject) => {
    setTimeout(() => {
      if (Math.random() < 0.2) {
        console.log('inner success');
        resolve('success');
      } else {
        console.log('inner failed');
        reject('failed');
      }
    }, 1000 * Math.random());
  });
}

请实现这个函数:执行函数fn,直至成功。除非超过重试次数或者超时。

function runWithRetry(fn, retryTimes, timeout) {
    // coding here
}