{"componentChunkName":"component---src-templates-blog-post-js","path":"/2019/02/02/single-input-source/","result":{"data":{"markdownRemark":{"html":"<p>记录一下最近对单一输入源的理解。</p>\n<p>最近在做的一个项目是这样的，一个音频播放网站，非 SPA，就像所有的音乐网站一样，所有页面的底部都有一个独立的音频播放器组件，在任意页面，如果有音频的播放按钮，点击这个按钮，播放器就会开始播放这个音频，并且显示这个音频的详细信息，比如 title, cover image, author。</p>\n<p>之前的实现方案是，点击页面上的播放按钮后，会把当前此音频的所有信息通过 custom event dispatch 给完全独立的音频播放器，音频播放器通过 <code class=\"language-text\">window.addEventListener()</code> 监听这个 custom event，然后播放此新的音频并在界面上所示它的信息。</p>\n<p>这样带来的问题是，在播放器组件，需要显示音频的 title/cover image/author，但在各个页面上，不一定显示这些信息，比如页面 A 只显示音频的 title，页面 B 只需要 cover image。但为了能在播放器组件上显示完整，在后端生成这个页面时不得不去获取音频的完整数据，虽然在页面上不需要显示出来。比如在访问页面 A，本来我只需要获取音频的 title，但实际我要去获取它的 title/cover image/author 等完整信息。</p>\n<p>当页面多了以后，就会发生漏掉获取音频的某些属性，导致点击播放按钮后播放器崩溃，或者虽然不崩溃，但显示空白 (后者有时还不容发现)。</p>\n<p>此时，音乐播放器面临输入源来自多个的问题，多个输入源可能导致状态/数据不一致。</p>\n<p>然后我就想到了是不是可以把输入源单一化。</p>\n<p>新的解决方案是这样的，在任意页面点击的播放按钮后，我只把当前音频的 id 通过 custom event 发送到音频播放器，然后音频播放器再通过音频的 id 访问 API，从 API 中拿到该音频的详细信息，然后显示和播放。</p>\n<p>虽然多了一次网络请求，但它带来的好处不言而预，每个页面不再需要去获取多余的音频属性，音乐播放器只从 API 拿数据，能保证数据的完整性。</p>\n<p>其实想想，redux 也可以算是一种单一输入源的方案。</p>\n<p>在 Android/iOS app 的开发中，我们有时会把网络请求的结果缓存在本地数据库比如 SQLite 中，等下次打开时，先从本地数据库中加载缓存显示，然后再发网络请求，待网络请求返回后，先更新缓存，再将网络请求回来的数据直接显示到界面上。这时，界面上的数据就有两个输入源了，一个是缓存，一个是网络请求。更好的办法是，UI 永远只从缓存加载数据，而网络请求的结果只用来更新缓存。</p>\n<blockquote>\n<p>单一读取源，多个写入源。</p>\n</blockquote>","frontmatter":{"title":"对单一输入源的理解","date":"February 02, 2019"}}},"pageContext":{"slug":"/2019/02/02/single-input-source/"}},"staticQueryHashes":["3159585216"]}