本周我们 36 人学了什么

程序员这行如果想一直做下去,那么持续学习是必不可少的。

大家找工作通常会喜欢技术氛围好点的团队,因为这样能够帮助自己更好的成长,但是并不是每个团队都拥有这样的氛围。于是萌发一个念头,想建立一个地方,让一些人能在这块地方记录自己学习到的内容。这些内容通常会是一个小点,可能并不足以写成一篇文章。但是这个知识点可能很多人也不知道,那么通过这种记录的方式让别人同样也学习到这个知识点就是一个很棒的事情了。

如果你也想参与这个记录的事情,欢迎贡献你的一份力量,地址在这里

本周总共有 36 个人贡献了它所学到的知识,以下是一些整合后的内容,更详细的内容推荐前往仓库阅读。

笔者在微信环境中直播功能的实践

兼容问题

视频兼容相关

在安卓中,直接使用原生 video 会导致全屏播放,盖住所有元素,因此使用 x5 播放器。但是 x5 播放器还是存在问题,虽然不会盖住元素,但是会自己添加特效(盖一层导航栏蒙层)。

<video
  className='live-detail__video vjs-big-play-centered'
  id='live-player'
  controls={false}
  playsInline
  webkit-playsinline='true'
  x5-video-player-type='h5'
  x5-video-orientation='portrait'
  x5-playsinline='true'
  style={style}
/>

这样可以在安卓下使用 x5 播放器, playsInlinewebkit-playsinline 属性可以在 iOS 环境下启用内联播放。但是通过属性设置内联播放兼容性并不怎么好,所以这时候我们需要使用 iphone-inline-video 这个库,通过 enableInlineVideo(video) 就可以了。

视频自动播放

在安卓下视频自动播放的兼容性很差,因此只能让用户手动触发视频播放。但是在 iOS 下可以通过监听微信的事件实现视频的自动播放。

document.addEventListener("WeixinJSBridgeReady", function () {
    player.play()
}, false)

iOS 下协议问题

因为页面使用的是 HTTPS 协议,iOS 强制规定在 HTTPS 页面下也必须使用安全协议。因此使用 ws 协议的话在 iOS 下报错,后续使用 wss 协议解决。

体验问题

iOS 下键盘弹起收下

在 iOS 中,输入框弹起键盘前后,页面都可能出现问题,需要监听下键盘弹起收起的状态,然后自己滚动一下。

// 监听键盘收起及弹出状态
document.body.addEventListener('focusout', () => {
  if (isIphone()) {
    setTimeout(() => {
      document.body.scrollTop = document.body.scrollHeight
    }, 100)
  }
})

document.body.addEventListener('focusin', () => {
  if (isIphone()) {
    setTimeout(() => {
      document.body.scrollTop = document.body.scrollHeight
    }, 100)
  }
})

性能优化

聊天数据渲染

考虑到直播中聊天数据频繁,因此所有接收到的数据会先存入一个数组 buffer 中,等待 2 秒后统一渲染。

// 接收到消息就先 push 到缓存数组中
this.bufferAllComments.push({
  customerName: fromCustomerName,
  commentId,
  content,
  commentType
})
// 利用定时器,每两秒将数组中的中的 concat 到当前聊天数据中并清空缓存
this.commentTimer = setInterval(() => {
  if (this.bufferAllComments.length) {
    this.appendChatData(this.bufferAllComments)
    this.bufferAllComments = []
  }
}, 2000)

另外直播中其实涉及到了很多异步数据的拉取及状态的变更,这时候如果能使用 RxJS 能很好的解决数据流转的问题,后续可以尝试重构这部分的代码。

链表作为聊天数据的载体

同样考虑到直播中聊天数据频繁插入,因此使用链表来存储显示的聊天数据,目前只存储 50 条数据,这样删除前面的只要很简单。

  • 使用链表的原因是考虑到频繁的去除数组头部数据去造成空间复杂度的问题
  • 另外也实现了支持迭代器的功能,代码如下:
[Symbol.iterator] () {
  let current = null; let target = this
  return {
    next () {
      current = current != null ? current.next : target.head
      if (current != null) {
        return { value: current.value, done: false }
      }
      return { value: undefined, done: true }
    },
    return () {
      return { done: true }
    }
  }
}

JS

数组求和

let arr = [1, 2, 3, 4, 5]
eval(arr.join('+'))

数组完全展开

function myFlat(arr) {
  while (arr.some(t => Array.isArray(t))) {
   	arr = ([]).concat.apply([], arr);
  }
  return arr;
}
var arrTest1 = [1, [2, 3, [4]], 5, 6, [7, 8], [[9, [10, 11], 12], 13], 14];
// Expected Output: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14]
console.log(myFlat(arrTest1))

实现 sleep 函数

function sleep(interval) {
  return new Promise(resolve => {
    setTimeout(resolve, interval);
  })
}
async function test() {
  for (let index = 0; index < 10; index++) {
    console.log(index);
    await sleep(2000)
  }
}

正则过滤违规词

var ma = "大xx".split('');
var regstr = ma.join('([^\u4e00-\u9fa5]*?)');
var str = "这是一篇文章,需要过滤掉大xx这三个词,大xx中间出汉字以外的字符 大_/_傻a1v逼和 大傻a1v逼";
var reg = new RegExp(regstr , 'g');
str.replace(reg,"<替换的词>");

Node

开启 Gzip

const express = require('express');
const compression = require('compression');
const app = express();
app.use(compression());

统计 Git 代码行数

const { exec } = require('child_process');
const { argv } = require('yargs');

const readLines = stdout => {
  const stringArray = stdout
    .toString()
    .split(/(\n)/g)
    .filter(str => str !== '\n' && str);
  const dataArray = [];
  stringArray.map(str => {
    const data = str.split(/(\t)/g).filter(str => str !== '\t');
    const [newLine, deletedLine, filePath] = data;
    dataArray.push({ newLine, deletedLine, filePath });
  });
  return dataArray;
};


try {
  if (!argv.commit) throw new Error('')
  exec(`git diff ${argv.commit} --numstat`, (error, stdout, stderr) => {
    console.table(readLines(stdout));
  });
} catch (e) {
  console.log(e);
}

实现一个only函数

var obj = {
    name: 'tobi',
    last: 'holowaychuk',
    email: 'tobi@learnboost.com',
    _id: '12345'
};

const only = (obj, para) => {
    if (!obj || !para) { new Error('please check your args!') }
    let newObj = {};
    let newArr = Array.isArray(para) ? para : typeof (para) === 'string' ? para.split(/ +/) : [];
    newArr.forEach((item) => {
        if (item && obj[item] && !newObj[item]) {
            newObj[item] = obj[item];
        }
    })
    return newObj;
}
// {email: "tobi@learnboost.com", last: "holowaychuk", name: "tobi"}
console.log(only(obj, ['name', 'last', 'email']));
console.log(only(obj, 'name last    email'));

其他

工作中培养起来的几点认知

  1. 优先做最重要的事情,(可以自己写在笔记本上,每天的任务,也可以利用todolist类似的软件)
  2. 懂得“闭环思维”,(对领导定期汇报项目进展,对同事、下属及时同步项目进度)
  3. 拥有解决问题并快速解决问题的能力(解决各种问题,锻炼解决问题的思维,一条路不通要想别的方法)
  4. 做一个靠谱、聪明、皮实、值得信赖的人。提高自己的不可替代性。
  5. 凡事有交代,件件有着落,事事有回音。
  6. 感激bug,是bug让自己成长,要成长必须多解决bug.多承担任务。
  7. 积极乐观,做一个正能量的人。(远离负能量的人和事)

一段脚本,数组数据量超额后,内存突然变小了?

最后

这是一个需要大家一起分享才能持续下去的事情,光靠我一人分享是做不下去的。欢迎大家参与到这件事情中来,地址在这里

关注作者公众号 与十万前端一起学习
加入前端进阶交流群 扫描二维码回复 加群 学习
极客时间 199 元大红包 购买课程还可获得12元返现
上次更新: 2019/8/4 下午10:41:45