给博客改了字体,在mac上显示瘦瘦的,怎么说呢,其实现在这个字体也挺不怎么合我之意,有点太细了,不稳重。但是默认的字体实在是有点不能接受,要是有特别是中文字体,挺难求的,而且还要免费,也是……
前端录制麦克风音频
在前端去录制麦克风音频,听起来好简单啊,但是后来发现是个大坑。这个问题要分解:
- 麦克风
- 音频
- 录制
获取麦克风输入比较简单,用webrtc的接口getUserMedia就可以实现了,但是怎么录制?getUserMedia得到的是stream,stream不是buffer,也不分chunks,所以你想要把stream转换为buffer,没办法,必须还得靠高级api。MediaRecorder本来可以用,但是safari不兼容,内心MMP。录制视频用canvas一帧一帧保存起来就行了,但是录制音频……最后找来找去,AudioContext这个api可以用,但是safari只有在11.2版本之后才支持webkitAudioContext,所以,只有用这货才能实现。
总结,在支持MediaRecorder的系统中使用MediaRecorder录制,在iOS中,最多兼容到使用webkitAudioContext去实现,有一个包可以用,就是audio-recorder-polyfill,想法真不错,赞一个。
今天看到消息称,网易博客将在18年11月30号全面关闭。我最早使用网易博客,也不过是2008年,大概写了两三年之后,就厌烦了浮夸的界面,和莫名其妙的广告,并且开始维护自己的独立域名博客。媒体称blogbus等为个人博客并不完全正确,因为“个人”这个词用在第三方平台上并不恰当,顶多算“博客服务”,就像公众号一样,称“个人公众号”也很奇怪。所以说,并不能称个人博客完蛋了,迟早有一天博客又会受到亲耐,至少在传播学意义上RSS还很有市场。就让那些公众号,微博,朋友圈儿都去吧,没事,我还是会常常在自己的博客写点东西。
其实很简单,substr按字,substring按位:
var str = '我很高兴ho~'
str.substring(str.length - 5, 5) // 高兴h
str.substr(str.length - 5, 5) // 高兴ho~
开源已经是软件领域占据绝对主导的一种策略。但是,很不幸,大部分人对开源的认知都无外乎两个点:“免费”“开箱即用”。所谓免费就是说你开源的软件,我不用买许可证,直接用,你的协议最好还是MIT,这样我用起来一点版权顾虑都没有。开源=免费,这几乎成为行业共知。而“开箱即用”则体现在使用者对开源软件的依赖性,它们希望一个开源软件可以按照自己的想法工作,如果不行的情况下,就去给软件作者提issue。实际上,在我看来,“免费软件”和“开源”完全是两个层面的事。开源的真正意义是,让原本封闭的独裁的技术公开,让其他开发者可以从中学习,在自己的产品里使用开源代码里面的思想、思路、甚至是实现方式,而非提供完整的产品免费给人用。但现在行业里面曲解开源精神,以github为主导的开源世界实际上是推崇“开源免费软件”这一完整的概念,而非“开源”概念本身,也就是说,一个开源项目的作者,被要求把这个项目做成一个完整的,其他开发者拿过去就开箱即用的,而且还要有完整文档的,甚至issue反馈即时的项目。这其实是做软件的思路,而非做开源的思路,开源变成了软件的一种分发方式,开源精神本身反而在这种潮流中被淡忘,甚至如果不按这种模式行事的开源项目,还会被数落。开发者不仅不感谢开源者将自己的思想公之于众,反而以形式化的要求去数落他,这样而言,他大可以不开源了,自己好好把项目做好,赚更多钱,而对于那些叫嚣开源项目完整性的人,多半不喜欢去看源码,而喜欢看文档,也就是那类拿来主义而已。
isObject
JS里面判断一个变量是否为object类型其实比较麻烦,除了array和null会干扰以外,我们知道,所有的衍生数据类型的本质都是object,要想知道一个数据是否是单纯的object,我们就要排除这些干扰,直接检测这个变量的constructor:
function isObject(value) { return value && typeof value === 'object' && value.constructor === Object }
-
运行了一下代码发现constrcutor单词拼写错误,改正constructor
-
已修正,谢谢指出#589 回复给#588 否子戈 2018-08-27 18:22
终于又重写完一个库,改名为databaxe,是一个前端数据请求管理相关的库,在datamanager.js的基础上修改而来,使用了indexedDB和webworker,是一个现代化的数据请求管理工具。它的理念什么的已经在相关文章里面介绍过了:
这次的改版(改名)是为了简化概念,重新提炼api,并且将同步转化为异步,将之前容易混淆的地方全部修改过,变成单一可理解的api。特别是对get方法进行改造,之前的get方法基于localStorage,是同步的,现在基于indexedDB,是异步的,与数据请求保持一致的行为操作模式,让使用起来更方便新手入门。同时开放了dispatch接口,时它拥有更新本地数据的能力。
要了解这个库移步DataBaxe。
这几天真的是下了苦心,把之前的四个包完完整整的重写了一遍,并将作为自己今后开发的开箱必用包,它们分别是hello-events(事件绑定与触发管理),hello-storage(localStorage等本地化存储简化操作),hello-worker(webworker简便使用),hello-indexeddb(超简单indexeddb使用包),接下来打算把之前写的datamanaer.js重写一下,要用hello-什么做名字还没想好,但是肯定会是最完美的前端数据获取模式。完成这个之后,就是要把hst-virtual-dom再重写一遍,把之前写的toex用上,这样就可以让virtual dom这块完美收官了。
Blob和ArrayBuffer的区别
周末趁没事,就把之前写的一个包重新写了一遍。这个包的作用是为开发者提供更加快捷的indexedDB操作,免除一切烦恼,开箱就用起来。indexedDB是web标准,被大部分现代浏览器完整支持。和localStorage不同的是,indexedDB是真的完整存储js对象的引擎,它甚至支持存储new Date()的值,其他一些基础的js对象类型也可能是支持的。而localStorage是只能存储字符串的,要存储对象,必须通过JSON等进行序列化,而JSON不支持循环嵌套。另外一点就是,localStorage是同步的,indexedDB是异步的。
基于对复杂的indexedDB原生接口进行封装的思路,我发布了hello-indexeddb这个包,可以通过下面这个命令安装
npm install --save hello-indexeddb
完整的文档在github上,可以点击这里阅读。都是key-value数据库,它和localStorage的本质区别在哪里呢?我认为数据库的本质能力是分层检索能力。检索能力对于localStorage简直就是无,它只能通过一个key得到一个value,而且是字符串的。而indexedDB可以通过创建索引进行检索,查询某个object的时候,可以通过主键快速get,也可以通过索引来快速query,这里的索引在代码层面就是一个被记录的object的属性。这看上去好像也没什么,比如我可以通过构造多种变形的key来保存localStorage,然后自己封装一套检索方法来进行查询,甚至我自己构建一套localStorage的索引来快速查询。这当然是可以的,从这点上来讲,indexedDB甚至没有localStorage有优势,因为localStorage是同步的,更直观,而且不会出现事件循环错误,也就不需要事务机制。但是同步有同步的坏处,那就是阻塞页面进程。
读完stackoverflow上的这个讨论后我更加确信localStorage是有局限的,也就是说,它真的真的仅仅适合那些非常小、碎片化的数据存储,而indexedDB才是完整的长久存储数据的解决方案。这也就是说,在一个web应用中,应该合理的选择使用localStorage还是indexedDB。大家之所以那么青睐使用localSotrage,最大的原因莫过于它的接口太过简单了。不过想要让indexedDB变得简单也非常容易,就是使用我上面的包。你甚至可以这么用:
async function() {
let idb = new HelloIndexedDB({ key: 'key' })
await idb.put({ key: 'my_key', value: 'my_value' })
let obj = await idb.get('my_key')
}
就是这么简单,跟localStorage相比,就是异步和同步的区别。在对put这个操作的适合,转换一下localStorage里面的set操作的思维,然后,就非常自然的切换到了indexedDB的怀抱里面。要知道,get回来的,是一个拥有上下文的真实的js对象,而非字符串序列化和反序列化的结果。
就这样,拥抱indexedDB吧~