small is better than big 我的读书方法论

床底下秘密 我是一个毅力不是很够的人。我曾经下定决心要锻炼身体,买了一些健身器材,例如瑜伽垫,仰卧起坐的器材,俯卧撑的器材。然而三分钟的热度过后,我把瑜伽垫卷了起来,塞到床底下。把仰卧起坐的器材拆开,也塞到了床底下。 所以每次我都不敢看床底下,那里塞满了我的羞愧。我常常想,我这不就是永远睡在羞愧之上吗? 那么,是什么让我放弃了自己的目标,慢慢活成了自己讨厌的样子呢? 之前和朋友聊天,我们有一段时间没见了。我突然觉得他也太能聊了,说了很多我不知道的新鲜事,还有一些可以让人茅塞顿开的想法。完了之后,他劝我让我多读书。我觉得这个想法很多。我是确实需要读书了。毕竟我的床底下已经没有空间再塞其他的东西了。 于是我在多看阅读上买了一下电子书,在京东上买了一些实体书,然后又买了一个kindle。在读书的过程中,有时候作者也会推荐你看一些其他的书。我给自己定了2018年我的阅读计划,给自己定下要看哪些书。 看书的方法 当我决定要看书,并且为此付出了不少的金钱的情况下。我是非常不愿因让我的金钱的付出白白打水漂的,毕竟买书以及买设备,这不是免费的服务。于是我给自己指定了一个非常完善的定量阅读标准 读书方法v1.0.0 版 如下 每天至少看三本书 每本书看50页 人要有标准才能判断是否达标,没有标准,没有数字化的支撑,那是很难以持续的。比如说中国的菜谱,做某道菜中写了一句:加入少许盐。中国人看了会想,那我就按照口味随便加点盐吧。外国人就会被搞得非常迷糊,少许是多少克盐? 20g, 30g? 完全没有标准嘛。 按照读书方法 v1.0.0版,我看了几天,这个效果是很好的。但是我很累,电子书50页可不是个小数目。有时候很难完成的。于是我必须要升级我的读书方法。 读书方法v1.0.1 版 如下 每天至少看三本书 每本书看10页 按照读书方法v1.0.1 版,我看了几天,虽然读书的进度很慢,但是我很容易有满足感,因为这个目标是很容易就达成的。因为你随便去上个厕所,看个10页电子书也是绰绰有余的。但是这个版本也有个问题。 如果我今天看的这本书看的流连忘返,一不小心忘记看页码了,居然不知不觉读了38页,那么是不是已经消耗了未来几天的阅读量呢,明天这本书要不要度呢? 所以,我要升级我的读书方法。 读书方法v1.0.2版: 每天至少读三本书 每本书至少读10页 我按照这个方法,感觉做的不错。每天都有一定的阅读量要看,而且阅读量不是很大,不会让我觉得很累。而且当我完成了这个目标,我是会获得不小的满足感。 大目标分解成小目标去逐个击破,这是我这篇文章的核心观点。 冲量公式 I = F x T 冲量是力的时间累积效应的量度,是矢量。如果物体所受的力是大小和方向都不变的恒力F,冲量I就是F和作用时间t的乘积。 冲量是描述力对物体作用的时间累积效应的物理量。力的冲量是一个过程量。在谈及冲量时,必须明确是哪个力在哪段时间上的冲量。 个人好习惯的养成,不是一蹴而就的,而是类似于物理学冲量的概念:力在一段时间内的累积,是过程量 三分钟的热度对应的冲量:I = F_max x T_min。使用很大的力,作用时间超短,基本上没啥效果,冲量趋近于零。 微习惯对应的冲量:I = F_min x T_max。使用很小的力,做长时间的积累。冲量不会趋近于零,而是会慢慢增长,然后趋近于一个稳定水平。比如你给自己规定每天看1页书,但是大多数情况下,如果你做了看书的动作,基本上你看书的页数一定会大于1页。 看什么样的书 我自己喜欢看计算机,心理学,历史人文方面的出版书籍。而我的选择标准有两个,符合任一一个,我都会去看。 要有用。无论是对我的专业知识,还是对人际交往,金融理财等方面要用有益之处 要有趣。没趣的书我是断然不会去看的。 读书实际上是读人,一流作家写的一流的书,三流作家只能写出九流的书。

2018-02-13 14:57:23 · 1 min · Eddie Wang

基于 WebRTC 构建 Web SIP Phone

0 阅前须知 本文并不是教程,只是实现方案 我只是从WEB端考虑这个问题,实际还需要后端sip服务器的配合 jsSIP有个非常不错的在线demo, 可以去哪里玩耍,很好玩呢 try jssip 1. 技术简介 WebRTC: WebRTC,名称源自网页即时通信(英语:Web Real-Time Communication)的缩写,是一个支持网页浏览器进行实时语音对话或视频对话的API。它于2011年6月1日开源并在Google、Mozilla、Opera支持下被纳入万维网联盟的W3C推荐标准 SIP: 会话发起协议(Session Initiation Protocol,缩写SIP)是一个由IETF MMUSIC工作组开发的协议,作为标准被提议用于创建,修改和终止包括视频,语音,即时通信,在线游戏和虚拟现实等多种多媒体元素在内的交互式用户会话。2000年11月,SIP被正式批准成为3GPP信号协议之一,并成为IMS体系结构的一个永久单元。SIP与H.323一样,是用于VoIP最主要的信令协议之一。 一般来说,要么使用实体话机,要么在系统上安装基于sip的客户端程序。实体话机硬件成本高,基于sip的客户端往往兼容性差,无法跨平台,易被杀毒软件查杀。 而WebRTC或许是更好的解决方案,只要一个浏览器就可以实时语音视频通话,这是很不错的解决方案。WebSocket可以用来传递sip信令,而WebRTC用来实时传输语音视频流。 2. 前端WebRTC实现方案 其实我们不需要去自己处理WebRTC的相关方法,或者去处理视频或者媒体流。市面上已经有不错的模块可供选择。 2.1 jsSIP jsSIP是JavaScript SIP 库 功能特点如下: 可以在浏览器或者Nodejs中运行 使用WebSocket传递SIP协议 视频音频实时消息使用WebRTC 非常轻量 100%纯JavaScript 使用简单并且具有强大的Api 服务端支持 OverSIP, Kamailio, Asterisk, OfficeSIP,reSIProcate,Frafos ABC SBC,TekSIP 是RFC 7118 and OverSIP的作者写的 下面是使用JsSIP打电话的例子,非常简单吧 // Create our JsSIP instance and run it: var socket = new JsSIP.WebSocketInterface('wss://sip.myhost.com'); var configuration = { sockets : [ socket ], uri : 'sip:alice@example.com', password : 'superpassword' }; var ua = new JsSIP.UA(configuration); ua.start(); // Register callbacks to desired call events var eventHandlers = { 'progress': function(e) { console.log('call is in progress'); }, 'failed': function(e) { console.log('call failed with cause: '+ e.data.cause); }, 'ended': function(e) { console.log('call ended with cause: '+ e.data.cause); }, 'confirmed': function(e) { console.log('call confirmed'); } }; var options = { 'eventHandlers' : eventHandlers, 'mediaConstraints' : { 'audio': true, 'video': true } }; var session = ua.call('sip:bob@example.com', options); 2.2 SIP.js sip.js项目实际是fork自jsSIP的,这里主要介绍它的服务端支持情况。其他接口自己自行查阅 ...

2018-02-11 14:44:58 · 2 min · Eddie Wang

不常用却很有妙用的事件及方法

1 visibilitychange事件 触发条件:浏览器标签页被隐藏或显示的时候会触发visibilitychange事件. 使用场景:当标签页显示或者隐藏时,触发一些业务逻辑 document.addEventListener("visibilitychange", function() { console.log( document.visibilityState ); }); 2 storage事件 触发条件:使用localStorage or sessionStorage存储或者修改某个本地存储时 使用场景:标签页间通信 // AB页面同源 // 在A 页面 window.addEventListener('storage', (e) => {console.log(e)}) // 在B 页面,向120打个电话 localStorage.setItem('makeCall','120') // 然后可以在A页面间有输出, 可以看出A页面 收到了B页面的通知 ...key: "makeCall", oldValue: "119", newValue: "120", ... 3 beforeunload事件 触发条件:当页面的资源将要卸载(及刷新或者关闭标签页前). 当页面依然可见,并且该事件可以被取消只时 使用场景:关闭或者刷新页面时弹窗确认,关闭页面时向后端发送报告等 window.addEventListener("beforeunload", function (e) { var confirmationMessage = "\o/"; e.returnValue = confirmationMessage; // Gecko, Trident, Chrome 34+ return confirmationMessage; // Gecko, WebKit, Chrome <34 }); 4 navigator.sendBeacon 这个方法主要用于满足 统计和诊断代码 的需要,这些代码通常尝试在卸载(unload)文档之前向web服务器发送数据。过早的发送数据可能导致错过收集数据的机会。然而, 对于开发者来说保证在文档卸载期间发送数据一直是一个困难。因为用户代理通常会忽略在卸载事件处理器中产生的异步 XMLHttpRequest 。 ...

2018-02-11 14:34:17 · 1 min · Eddie Wang

mac vscode 更新失败 Permission denied解决办法

0. 现象 Could not create temporary directory: Permission denied 1. 问题起因 在 /Users/username/Library/Caches/目录下,有以下两个文件, 可以看到,他们两个的用户是不一样的,一个是root一个username, 一般来说,我是以username来使用我的mac的。就是因为这两个文件的用户不一样,导致了更新失败。 drwxr-xr-x 6 username staff 204B Jan 17 20:33 com.microsoft.VSCode drwxr--r-- 2 root staff 68B Dec 17 13:51 com.microsoft.VSCode.ShipIt 2. 解决方法 注意: 先把vscode 完全关闭 // 1. 这一步是需要输入密码的 sudo chown $USER ~/Library/Caches/com.microsoft.VSCode.ShipIt/ // 2. 这一步是不需要输入密码的, 如果不进行第一步,第二步会报错 sudo chown $USER ~/Library/Caches/com.microsoft.VSCode.ShipIt/* // 3. 更新xattr xattr -dr com.apple.quarantine /Applications/Visual\ Studio\ Code.app 3. 打开vscode Code > Check for Updates, 点击之后,你会发现Check for Updates已经变成灰色了,那么你需要稍等片刻,马上就可以更新,之后会跳出提示,让你重启vscode, 然后重启一下vscode, 就ok了。 ...

2018-02-11 14:20:01 · 1 min · Eddie Wang

IE11 0x2ee4 bug 以及类似问题解决方法

一千个IE浏览器访问同一个页面,可能报一千种错误。前端激进派对IE恨得牙痒痒,但是无论你爱,或者不爱,IE就在那里,不来不去。 一些银行,以及政府部门,往往都是指定必须使用IE浏览器。所以,一些仅在IE浏览器上出现的问题。总结起来问题的原因很简单:IE的配置不正确 下面就将一个我曾经遇到的问题: IE11 0x2ee4, 以及其他的问题的解决方案 1. IE11 SCRIPT7002: XMLHttpRequest: 网络错误 0x2ee4 背景介绍:在一个HTTPS域向另外一个HTTPS域发送跨域POTST请求时 这个问题在浏览器的输出内容如下,怪异的是,并不是所有IE11都会报这个错误。 SCRIPT7002: XMLHttpRequest: 网络错误 0x2ee4, 由于出现错误 00002ee4 而导致此项操作无法完成 stackoverflow上有个答案,它的思路是:在post请求发送之前,先进行一次get操作 这个方式我试过,是可行的。但是深层次的原因我不是很明白。 然而真相总有大白的一天,其实深层次的原因是,IE11的配置。 去掉检查证书吊销的的检查,解决0x2ee4的问题 解决方法 去掉check for server certificate revocation*, 也有可能你那边是中文翻译的:叫检查服务器证书是否已吊销 去掉检查发型商证书是否已吊销 点击确定 重启计算机 2 其他常规设置 2.1 去掉兼容模式, 使用Edge文档模式 下图中红色框里的按钮也要取消勾选 2.2 有些使用activeX,还是需要检查是否启用的 2.3 允许跨域 如果你的接口跨域了,还要检查浏览器是否允许跨域,否则浏览器可能默认就禁止跨域的 设置方法 internet选项 安全 自定义级别 启用通过跨域访问数据源 启用跨域浏览窗口和框架 确定 然后重启电脑

2018-02-11 14:12:19 · 1 min · Eddie Wang

Vue+ElementUI 手把手教你做一个audio组件

1. 简介 1.1. 相关技术 Vue Vue-cli ElementUI yarn (之前我用npm, 并使用cnpm的源,但是用了yarn之后,我发现它比cnpm的速度还快,功能更好,我就毫不犹豫选择yarn了) Audio相关API和事件 1.2. 从本教程你会学到什么? Vue单文件组件开发知识 Element UI基本用法 Audio原生API及Audio相关事件 音频播放器的基本原理 音频的播放暂停控制 更新音频显示时间 音频进度条控制与跳转 音频音量控制 音频播放速度控制 音频静音控制 音频下载控制 个性化配置与排他性播放 一点点ES6语法 2. 学前准备 基本上不需要什么准备,但是如果你能先看一下Aduio相关API和事件将会更好 Audio: 如果你愿意一层一层剥开我的心 使用 HTML5 音频和视频 3. 在线demon 没有在线demo的教程都是耍流氓 查看在线demon 项目地址 4. 开始编码 5. 项目初始化 ➜ test vue init webpack element-audio A newer version of vue-cli is available. latest: 2.9.2 installed: 2.9.1 ? Project name element-audio ? Project description A Vue.js project ? Author wangdd <wangdd@xxxxxx.com> ? Vue build standalone ? Install vue-router? No ? Use ESLint to lint your code? No ? Set up unit tests No ? Setup e2e tests with Nightwatch? No ? Should we run `npm install` for you after the project has been created? (recommended) npm ➜ test cd element-audio ➜ element-audio npm run dev 浏览器打开 http://localhost:8080/, 看到如下界面,说明项目初始化成功 ...

2018-02-09 13:44:13 · 7 min · Eddie Wang

你不知道的JSON.stringify()妙用

1. 语法 JSON.stringify(value[, replacer[, space]]) 一般用法: var user = {name: 'andy', isDead: false, age: 11, addr: 'shanghai'}; JSON.stringify(user); "{"name":"andy","isDead":false,"age":11,"addr":"shanghai"}" 2. 扩展用法 2.1. replacer replacer可以是函数或者是数组。 功能1: 改变属性值 将isDead属性的值翻译成0或1,0对应false,1对应true var user = {name: 'andy', isDead: false, age: 11, addr: 'shanghai'}; JSON.stringify(user, function(key, value){ if(key === 'isDead'){ return value === true ? 1 : 0; } return value; }); "{"name":"andy","isDead":0,"age":11,"addr":"shanghai"}" 功能2:删除某个属性 将isDead属性删除,如果replacer的返回值是undefined,那么该属性会被删除。 var user = {name: 'andy', isDead: false, age: 11, addr: 'shanghai'}; JSON.stringify(user, function(key, value){ if(key === 'isDead'){ return undefined; } return value; }); "{"name":"andy","age":11,"addr":"shanghai"}" 功能3: 通过数组过滤某些属性 只需要name属性和addr属性,其他不要。 ...

2018-02-09 13:27:15 · 1 min · Eddie Wang

ECharts 轮流高亮中国地图各个省份

1. 小栗子 最早我是想通过dispatchAction方法去改变选中的省份,但是没有起作用,如果你知道这个方法怎么实现,麻烦你可以告诉我。 我实现的方法是另外一种。 dispatchAction({ type: 'geoSelect', // 可选,系列 index,可以是一个数组指定多个系列 seriesIndex?: number|Array, // 可选,系列名称,可以是一个数组指定多个系列 seriesName?: string|Array, // 数据的 index,如果不指定也可以通过 name 属性根据名称指定数据 dataIndex?: number, // 可选,数据名称,在有 dataIndex 的时候忽略 name?: string }) 后来我改变了一个方法。这个方法的核心思路是定时获取图标的配置,然后更新配置,最后在设置配置。 var myChart = echarts.init(document.getElementById('china-map')); var COLORS = ["#070093", "#1c3fbf", "#1482e5", "#70b4eb", "#b4e0f3", "#ffffff"]; // 指定图表的配置项和数据 var option = { tooltip: { trigger: 'item', formatter: '{b}' }, series: [ { name: '中国', type: 'map', mapType: 'china', selectedMode : 'single', label: { normal: { show: true }, emphasis: { show: true } }, data:[ // 默认高亮安徽省 {name:'安徽', selected:true} ], itemStyle: { normal: { areaColor: 'rgba(255,255,255,0.5)', color: '#000000', shadowBlur: 200, shadowColor: 'rgba(0, 0, 0, 0.5)' }, emphasis:{ areaColor: '#3be2fb', color: '#000000', shadowBlur: 200, shadowColor: 'rgba(0, 0, 0, 0.5)' } } } ] }; // 使用刚指定的配置项和数据显示图表。 myChart.setOption(option); myChart.on('click', function(params) { console.log(params); }); setInterval(function(){ var op = myChart.getOption(); var data = op.series[0].data; var length = data.length; data.some(function(item, index){ if(item.selected){ item.selected = false; var next = (index + 1)%length; data[next].selected = true; return true; } }); myChart.setOption(op); }, 3000); 2. 后续补充 我从这里发现:https://github.com/ecomfe/echarts/issues/3282,选中地图的写法是这样的,而试了一下果然可以。主要是type要是mapSelect,而不是geoSelect ...

2018-02-09 13:16:53 · 1 min · Eddie Wang

一行命令搭建简易静态文件http服务器

简易服务器:在命令执行的所在路径启动一个http服务器,然后你可以通过浏览器访问该路径下的所有文件。 在局域网内传文件,或者自己测试使用都是非常方便的。 1. 基于python 1.1. 基于Python2 python -m SimpleHTTPServer port > python -m SimpleHTTPServer 8099 Serving HTTP on 0.0.0.0 port 8099 ... 127.0.0.1 - - [24/Oct/2017 11:07:56] "GET / HTTP/1.1" 200 - 1.2. 基于python3 python3 -m http.server port > python3 -m http.server 8099 Serving HTTP on 0.0.0.0 port 8099 (http://0.0.0.0:8099/) ... 127.0.0.1 - - [24/Oct/2017 11:05:06] "GET / HTTP/1.1" 200 - 127.0.0.1 - - [24/Oct/2017 11:05:06] code 404, message File not found 127.0.0.1 - - [24/Oct/2017 11:05:06] "GET /favicon.ico HTTP/1.1" 404 - 2. 基于nodejs 首先你要安装nodejs ...

2018-02-09 13:01:14 · 1 min · Eddie Wang

120行代码实现 浏览器WebRTC视频聊天

本例子是参考webrtc-tutorial-simple-video-chat做的。 这个教程应该主要是去宣传ScaleDrone的sdk, 他们的服务是收费的,但是免费的也可以用,就是有些次数限制。 本栗子的地址 本栗子的pages地址 因为使用的是ScaleDrone的js sdk, 后期很可能服务不稳定之类的 1. 准备 使用最新版谷歌浏览器(62版) 视频聊天中 一个是windows, 一个是mac stun服务器使用谷歌的,trun使用ScaleDrone的sdk,这样我就不用管服务端了。 2. 先上效果图 3. 再上在线例子点击此处 4. 源码分析 // 产生随机数 if (!location.hash) { location.hash = Math.floor(Math.random() * 0xFFFFFF).toString(16); } // 获取房间号 var roomHash = location.hash.substring(1); // 放置你自己的频道id, 这是我注册了ScaleDrone 官网后,创建的channel // 你也可以自己创建 var drone = new ScaleDrone('87fYv4ncOoa0Cjne'); // 房间名必须以 'observable-'开头 var roomName = 'observable-' + roomHash; var configuration = { iceServers: [{ urls: 'stun:stun.l.google.com:19302' // 使用谷歌的stun服务 }] }; var room; var pc; function onSuccess() {} function onError(error) { console.error(error); } drone.on('open', function(error){ if (error) { return console.error(error);} room = drone.subscribe(roomName); room.on('open', function(error){ if (error) {onError(error);} }); // 已经链接到房间后,就会收到一个 members 数组,代表房间里的成员 // 这时候信令服务已经就绪 room.on('members', function(members){ console.log('MEMBERS', members); // 如果你是第二个链接到房间的人,就会创建offer var isOfferer = members.length === 2; startWebRTC(isOfferer); }); }); // 通过Scaledrone发送信令消息 function sendMessage(message) { drone.publish({ room: roomName, message }); } function startWebRTC(isOfferer) { pc = new RTCPeerConnection(configuration); // 当本地ICE Agent需要通过信号服务器发送信息到其他端时 // 会触发icecandidate事件回调 pc.onicecandidate = function(event){ if (event.candidate) { sendMessage({ 'candidate': event.candidate }); } }; // 如果用户是第二个进入的人,就在negotiationneeded 事件后创建sdp if (isOfferer) { // onnegotiationneeded 在要求sesssion协商时发生 pc.onnegotiationneeded = function() { // 创建本地sdp描述 SDP (Session Description Protocol) session描述协议 pc.createOffer().then(localDescCreated).catch(onError); }; } // 当远程数据流到达时,将数据流装载到video中 pc.onaddstream = function(event){ remoteVideo.srcObject = event.stream; }; // 获取本地媒体流 navigator.mediaDevices.getUserMedia({ audio: true, video: true, }).then( function(stream) { // 将本地捕获的视频流装载到本地video中 localVideo.srcObject = stream; // 将本地流加入RTCPeerConnection 实例中 发送到其他端 pc.addStream(stream); }, onError); // 从Scaledrone监听信令数据 room.on('data', function(message, client){ // 消息是我自己发送的,则不处理 if (client.id === drone.clientId) { return; } if (message.sdp) { // 设置远程sdp, 在offer 或者 answer后 pc.setRemoteDescription(new RTCSessionDescription(message.sdp), function(){ // 当收到offer 后就接听 if (pc.remoteDescription.type === 'offer') { pc.createAnswer().then(localDescCreated).catch(onError); } }, onError); } else if (message.candidate) { // 增加新的 ICE canidatet 到本地的链接中 pc.addIceCandidate( new RTCIceCandidate(message.candidate), onSuccess, onError ); } }); } function localDescCreated(desc) { pc.setLocalDescription(desc, function(){ sendMessage({ 'sdp': pc.localDescription }); },onError); } 5. WebRTC简介 5.1. 介绍 WebRTC 是一个开源项目,用于Web浏览器之间进行实时音频视频通讯,数据传递。 WebRTC有几个JavaScript APIS。 点击链接去查看demo。 ...

2018-02-09 12:56:12 · 2 min · Eddie Wang