日问周刊 | 全栈面试汇总 | 第二期

勤学如春起之苗,不见其增,日有所长;辍学如磨刀之石,不见其损,日有所亏。html

我在 github 上新建了一个仓库 日问,天天至少一个问题。有关全栈,graphql,devops,微服务以及软技能,促进职业成长,欢迎交流。前端

以诸葛武侯的诫子书与君共勉react

夫君子之行,静以修身,俭以养德。非澹泊无以明志,非宁静无以至远。夫学须静也,才须学也,非学无以广才,非志无以成学。淫慢则不能励精,险躁则不能治性。年与时驰,意与日去,遂成枯落,多不接世,悲守穷庐,将复何及!linux

【Q037】linux 有哪些发行版,你最喜欢哪个

原文连接,欢迎讨论: 【Q037】linux 有哪些发行版,你最喜欢哪个git

开放问题,不过你至少得知道一个发行版...程序员

【Q036】http 状态码中 301,302和307有什么区别

原文连接,欢迎讨论: 【Q036】http 状态码中 301,302和307有什么区别github

  • 301,Moved Permanently。永久重定向,该操做比较危险,须要谨慎操做:若是设置了301,可是一段时间后又想取消,可是浏览器中已经有了缓存,仍是会重定向。
  • 302,Fount。临时重定向,可是会在重定向的时候改变 method: 把 POST 改为 GET,因而有了 307
  • 307,Temporary Redirect。临时重定向,在重定向时不会改变 method

【Q035】http 常见的状态码有哪些

原文连接,欢迎讨论: 【Q035】http 常见的状态码有哪些web

【Q034】如何实现一个 loading 动画

原文连接,欢迎讨论:【Q034】如何实现一个 loading 动画面试

【Q033】如何对接口进行限流]

原文连接,欢迎讨论: 【Q033】如何对接口进行限流redis

通常采用漏桶算法:

  1. 漏桶初始为空
  2. API 调用是在往漏桶里注水
  3. 漏桶会以必定速率出水
  4. 水满时 API 拒绝调用

漏桶算法

可使用 redis 的计数器实现

  1. 计数器初始为空
  2. API 调用计数器增长
  3. 给计数器设置过时时间,隔段时间清零,视为必定速率出水
  4. 计数器达到上限时,拒绝调用

固然,这只是大体思路,这时会有两个问题要注意

  1. 最坏状况下的限流是额定限流速率的2倍
  2. 条件竞争问题

不过实际实现时注意如下就行了(话说通常也是调用现成的三方库作限流...),能够参考我之前的文章

【Q032】js 中什么是 softbind,如何实现

原文连接,欢迎讨论:【Q032】js 中什么是 softbind,如何实现

【Q031】js 中如何实现 bind

原文连接,欢迎讨论: 【Q031】js 中如何实现 bind

最简单的 bind 一行就能够实现,而在实际面试过程当中也不会考察你太多的边界条件

Function.prototype.fakeBind = function(obj) {
  return (...args) => this.apply(obj, args)
}复制代码

测试一下

function f (arg) {
  console.log(this.a, arg)
}

// output: 3, 4
f.bind({ a: 3 })(4)

// output: 3, 4
f.fakeBind({ a: 3 })(4)复制代码

【Q030】linux 中如何打印全部网络接口

原文连接,欢迎讨论: 【Q030】linux 中如何打印全部网络接口

ifconfig

ifconfig 是最简单最经常使用,可是打印信息太多了

$ ifconfig复制代码

netstat

netstatip 也挺好用,特别是它们还能够打印路由表

$ netstat -i复制代码

ip

$ ip link

$ ip addr复制代码

【Q029】websocket 如何向特定的用户组推送消息

redis 处维护一个对象,记录每一个 group 所对应的 connections/sockets

{
  'Class:201901': [student1Socket, student2Socket]
}复制代码

当 client 刚连入 server 时,便加入某个特定的组,或者叫 room,好比 student01,刚开始连入 server,可能要加入 room:Student:01Class:201901Group:10086

【Q028】在linux中如何获取登陆的用户

【Q028】在linux中如何获取登陆的用户

$ who

$ last复制代码

【Q027】在前端开发中,如何获取浏览器的惟一标识

fingerprintjs2

【Q026】如何对接口进行压力测试

【Q025】简述 socket 创建的过程

一图胜千言

image

【Q024】在 postgres 中,查询时如何对 jsonb 数据格式化

使用 jsonb_pretty 函数,示例以下

> select jsonb_pretty('{"a": {"b": 4}}'::jsonb)
+----------------+
| jsonb_pretty   |
|----------------|
| {              |
|     "a": {     |
|         "b": 4 |
|     }          |
| }              |
+----------------+
SELECT 1
Time: 0.018s复制代码

【Q023】websocket 服务多节点部署时会有什么问题,怎么解决

借用 redis

【Q022】如何实现一个简单的 Promise

一个简单的 Promise 的粗糙实现,关键点在于

  1. pending 时, thenable 函数由一个队列维护
  2. 当状态变为 resolved(fulfilled) 时,队列中全部 thenable 函数执行
  3. resolved 时, thenable 函数直接执行

rejected 状态同理

class Prom {
  static resolve (value) {
    if (value && value.then) {
      return value 
    }
    return new Prom(resolve => resolve(value))
  }

  constructor (fn) {
    this.value = undefined
    this.reason = undefined
    this.status = 'PENDING'

    // 维护一个 resolve/pending 的函数队列
    this.resolveFns = []
    this.rejectFns = []

    const resolve = (value) => {
      // 注意此处的 setTimeout
      setTimeout(() => {
        this.status = 'RESOLVED'
        this.value = value
        this.resolveFns.forEach(({ fn, resolve: res, reject: rej }) => res(fn(value)))
      })
    }

    const reject = (e) => {
      setTimeout(() => {
        this.status = 'REJECTED'
        this.reason = e
        this.rejectFns.forEach(({ fn, resolve: res, reject: rej }) => rej(fn(e)))
      })
    }

    fn(resolve, reject)
  }


  then (fn) {
    if (this.status === 'RESOLVED') {
      const result = fn(this.value)
      // 须要返回一个 Promise
      // 若是状态为 resolved,直接执行
      return Prom.resolve(result)
    }
    if (this.status === 'PENDING') {
      // 也是返回一个 Promise
      return new Prom((resolve, reject) => {
        // 推动队列中,resolved 后统一执行
        this.resolveFns.push({ fn, resolve, reject }) 
      })
    }
  }

  catch (fn) {
    if (this.status === 'REJECTED') {
      const result = fn(this.value)
      return Prom.resolve(result)
    }
    if (this.status === 'PENDING') {
      return new Prom((resolve, reject) => {
        this.rejectFns.push({ fn, resolve, reject }) 
      })
    }
  }
}

Prom.resolve(10).then(o => o * 10).then(o => o + 10).then(o => {
  console.log(o)
})

return new Prom((resolve, reject) => reject('Error')).catch(e => {
  console.log('Error', e)
})复制代码

【Q021】React 中,cloneElement 与 createElement 各是什么,有什么区别

首参不同,直接上 API

React.cloneElement(
  element,
  [props],
  [...children]
)

React.createElement(
  type,
  [props],
  [...children]
)复制代码

【Q020】如何实现一个分布式锁

【Q019】如何实现选中复制的功能

它通常可使用第三方库 clipboard.js 来实现,源码很简单,能够读一读

主要有两个要点

  1. 选中
  2. 复制

选中

选中主要利用了 Selection API

选中的代码以下

const selection = window.getSelection();
const range = document.createRange();

range.selectNodeContents(element);
selection.removeAllRanges();
selection.addRange(range);

selectedText = selection.toString();复制代码

取消选中的代码以下

window.getSelection().removeAllRanges();复制代码

它有现成的第三方库可使用: select.js

复制

复制就比较简单了,execCommand

document.exec('copy')复制代码


我是山月,一个喜欢跑步与登山的程序员,我会按期分享全栈文章在我的公众号中。若是你对全栈面试,前端工程化,graphql,devops,我的服务器运维以及微服务感兴趣的话,能够关注我

若是你对全栈面试,前端工程化,graphql,devops,我的服务器运维以及微服务感兴趣的话,能够关注我

相关文章
相关标签/搜索