robbiemie/keep-learning

小🍠一面(day5)

Opened this issue · 2 comments

  1. 聊聊项目
  2. intersection-observer-polyfill 底层实现逻辑
  3. 讲讲性能指标(fcp)以及项目优化过程【参考答案
  4. tree-shaking 原理以及底层实现【查看答案
  5. esm 和 commonjs 之间的差异,分别说说他们之间的优缺点【查看答案
  6. vue 如何实现插件,源码分析,如何设计一个框架插件,以及如何设计中间件?【参考
  7. nuxt 框架中 asyncData 底层实现
  8. 如何实现虚拟列表
  9. 如何实现分片渲染【参考答案
  10. (结合上面的虚拟列表回答)如果元素高度是动态的,如何处理这种场景?【参考答案
  11. ServiceWorker 和 diskCache 区别
  12. 介绍一下 ssr 的渲染原理【查看答案
  13. 讲讲 serviceWoker 缓存离线包的应用,如果发布了一个异常离线包,该如何回滚处理离线包,如何做降级处理
  14. 客户端如何实现双全工通信更新离线包,web 端有什么手段呢?
  15. 讲讲如何设计 reactNative ui 组件库,ui 组件库如何实现多主题替换,组件库文档如何选型(storybook why?)
  16. 如何利用浏览器缓存应用实际业务开发中?
  17. 强缓存和协商缓存,结合 CDN
  18. serviceWoker api 接口,以及 serviceWorker 缓存存储位置,如何读取离线缓存?twitter 是如何应用离线缓存的?
  19. 实现一个带有重试机制的请求工具函数
// 要求
// 1. 使用 fetch 函数发起一次请求
// 2. 如果请求失败,则自动重试
// 3. 超过重试次数上限,抛出错误
async function request(url, rety = 3, timeout = 3000) {
}

题解

async function request(url, retry = 3, timeout = 3000) {
  
  let status = 'pending'
  let timer = null
  let remainTime = retry;

  function retryFetch({resolve, reject, remainTime}) {
    if(remainTime === 0) {
      return reject(new Error(`fail: more than ${retry} times`))
    }
    fetch(url)
      .then(res => {
        clearTimeout(timer)
        status = 'success'
        resolve(res)
      })
      .catch(e => {
        if(remainTime > 0) {
          retryFetch({resolve, reject, remainTime: remainTime - 1})
        } else {
          clearTimeout(timer)
          reject(e)
        }
      })
  }
  
  return new Promise((resolve, reject) => {
    timer = setTimeout(() => {
      if(status !== 'success') {
        reject(new Error(`fail: timeout more than ${timeout / 1000}s`))
      }
    }, timeout)

    retryFetch({resolve, reject, remainTime})
  })
}

request('https://www.baidu.com');
new Promise(resolve => {
  setTimeout(() => {
    resolve('3');
    console.log('t1')
  })
  resolve('1')
  resolve('2')
}).then(res => {
  console.log(res);
}).finally(res => {
  console.log(res)
})

new Promise(resolve => {
  setTimeout(() => {
    resolve('3');
    console.log('t1')
  })
  reject('1') // reject
  resolve('2')
}).then(res => {
  console.log(res);
  return res;
}).finally(res => {
  console.log(res)
})

利用 Promise.race 实现

// 使用示例
async function myAsyncOperation(): Promise<string> {
  // 模拟一个异步操作,比如发起网络请求
  return new Promise((resolve, reject) => {
    // 假设这里是一些异步逻辑
    setTimeout(() => {
      const success = Math.random() > 0.5; // 随机成功或失败
      if (success) {
        resolve('Operation succeeded');
      } else {
        reject(new Error('Operation failed'));
      }
    }, 500); // 假设异步操作在 500 毫秒内完成
  });
}

function retryWithTimeout(handler, retryCount = 0, timeout = 0) {
  
  async function fetchOperation(remainTimes) {
    while(remainTimes > 0) {
      try {
        return await Promise.race([
          handler(),
          new Promise((resolve, reject) => setTimeout(() => reject(new Error('the request is time out!')), timeout)),
        ])
      } catch(e) {
        remainTimes -= 1;
        console.log(`attempt ${retryCount - remainTimes} times, retrying...`);
      }
    }
    if(remainTimes === 0) throw new Error('the request is failed.')
  }
  return fetchOperation(retryCount)
}

retryWithTimeout(myAsyncOperation, 5, 3000)