NodeJS Event Loop 学习笔记

最近想要深入了解下 NodeJS 中 Event Loop 的工作机制,但网上的文章重复性较高,还派生出一些很容易混淆的概念,而且有些文章里举的例子甚至无法自圆其说。所以自己参照 Node 官方给的一篇介绍文章,和 Medium 上看到的一个系列文章,很好地介绍了 Event Loop 的工作原理,现在把学习笔记做个梳理:

  1. Node 主要通过 libuv 来实现异步机制,libuv 主要提供了两个功能:
    • Event Demultiplexer:代理 Node 发起的异步 I/O 请求,部分功能通过不同 OS 提供的异步机制(如 epoll/kqueue/IOCP 等)来执行,部分没有原生异步 API 支持的 I/O 功能,libuv 实现了一个线程池(默认线程数为4)来实现异步。应尽量避免使用线程池中的线程来执行异步,因为会造成性能问题(也可以通过设置$UV_THREADPOOL_SIZE来修改默认线程数)。
    • Event Queue:每个 cb 被称为一个 event,libuv 通过设置 Event Loop 执行机制,和多个 Event Queue 来执行异步 cb。
  2. l


阅读全文 »

iOS 下 JavaScript 实现复制功能

1. 背景

以下是对 iOS 下复制功能的简单实现,注意在 iOS 10 以下的版本中,以下代码是无效的

最近要实现一个小需求:iOS APP下,用户点击一个按钮,系统自动复制一段文本到系统剪贴板。通过查资料发现,iOS 出于安全性的考虑,对 Clipboard API 的使用有诸多限制。但是在 iOS 10 及以上版本中,可以通过 hack 的方式来实现该功能。

2. 方案

主要参考的是 SO 上的这个答案,在 iOS 10 及以上版本中,使用复制功能有以下限制:

  1. 只能复制<input><textarea>元素中的文本;
  2. 如果包含待复制文本的元素没有包含在一个<form>中,那它的contentEditable属性必须为true
  3. 第2步中的元素同时不能是readonly
  4. 待复制文本必须是被选中状态。

要满足上述4个限制,代码中需要做到:

  1. 把待复制文本放入<input><textarea>类型的元素 A 中;
  2. 保存 A 元素的contentEditablereadonly属性,以


阅读全文 »

前端热力图系统实现

1. 背景

今年6月开发了一个前端热力图系统,目前已经应用在公司的主要业务中,一直没时间做个总结,现在梳理一下实现思路。

先说下为什么要做这样一个系统,电商网站的一种常用营销手段,就是配置眼花缭乱的活动页展现给用户,有的用来展示各种商品,有的供用户领取优惠券。但屏幕的展示空间有限,如何配置不同的模块才能最大化利用页面空间,一种比较好的方式就是采集用户点击数据,绘制出热力图,供产品、运营和设计同学参考,不断优化模块配置,有效提升点击转化。

2. 系统架构

热力图架构

先将热力图系统进行子功能拆分,可以得到以下几个部分:

  1. 用户点击数据采集:包括页面埋点、数据入库;
  2. 热力图绘制:包括:数据读取、数据加工、热力图绘制;
  3. 数据查询平台:主要是按日期和活动ID查询自定义区域的点击数。

2.1 数据采集

数据采集部分,主要通过事件代理在body上绑定click事件,采集数据主要包括:

  1. x:点击事件触发相对于 document 的横坐标,主要取自于event.pageX
  2. y:点击事件触发相对于 document 的纵坐标,主要取自于event.pageY


阅读全文 »

iOS 8.1/8.2 第三方输入法无法响应 keyup 事件

这是前两天遇到的一个坑。场景是一个包含一个输入框和一个“提交”按钮(默认 disabled)的 H5 页面,当在输入框中输入合法数据后,“提交”按钮会变得可用,然后用户可以点击提交数据。

之前的实现是监听输入框的keyup事件,当输入合法数据后,修改按钮样式变为可用。

但部分用户反馈无论输入什么样内容,按钮始终不可点击,所以猜测可能是keyup事件没有响应。通过整理出问题的 OS,发现主要是 iOS 8.1/8.2两个版本。测试后发现的确是这两个版本的 WebView 下第三方输入法对keyup事件无响应。

最终的解决方案是修改为监听input事件,问题解决。先写这么多,留坑总结下两个事件的不同。


阅读全文 »

stringify 实现及 JSON 数据类型思考

背景

记之前遇见的一道面试题,让现场写出 JavaScript 中stringify函数的实现。首先写一下自己最开始的思路,然后针对里面的一些问题进行逐步修改,并且引出对 JSON 这种轻量级数据传输格式所拥有数据类型的学习与思考。

一、最初实现

首先给定题目

将一个 JSON 格式对象转换为字符串,转换后的结果可以通过JSON.parse()方法将该字符串重新转换为一个 JSON 对象。

先简化问题,将数据类型简单划分(并不正确,下文会给描述)为:对象(Object)、数组(Array)和字符串(String)这三种类型。对于 String,只需要简单的对它进行toString()调用,并包裹在"中处理,对于前两者则需要采取不同操作。考虑到他们的子元素也是 JSON 对象,定义具有递归性,所以代码也采用递归来实现。最初代码如下:

代码的思路就是传入一个对象,然后判断它的类型:1. 如果非数组和对象类型,就直接返回它的字符串形式;2. 如果是对象类型,则遍历每个键值对,判断每个键对应值的类型,如果是


阅读全文 »

React Native 下拉菜单容器实现

背景

本周算是把一个 react native 版的商家管理工具(iOS 版花花内嵌商家后台)完成,所以现在花一点时间来把其中一些值得记录下的东西整理一下写出来。 根据 UI 设计,很多页面都采下图的展示方式:

截图

可以看到,两个页面的结构相似:顶部都是若干个PickerIOS组件的集合(红色框部分),然后下面是不同的组件(蓝色框组件)。例如左图有3个PickerIOS而右图有4个PickerIOS,并且分别代表不同的筛选条件。左图中的内容组件包括一个图表以及一个列表,而右图只有一个列表。所以考虑把公共部分提取出一个公共组件,该组件可以实现:

  1. 红色框内的PickerIOS数量以及内容可以定制。
  2. 蓝色框内的内容组件可以作为一个属性传递给该组件,用来展示信息。
  3. 切换筛选条件,能够向后端请求数据,并更新内容组件。

功能实现

顶部的Picker集合采用配置的方式实现,即单独创建一个配置文件模块DropdownViewConfig.js,文件内容大致如下:

每个 key(如 platform 和 date 等)对


阅读全文 »

动态侧边导航栏 JS 实现

背景

来美丽说后做的第一个大的页面改版就是商家后台整个发宝页改版,感觉其中一个比较有意思的地方就是侧边导航栏的实现。页面内容非常多,涉及到商品的不同属性信息以及其他一些功能模块,所以整个页面的 js 实现也分模块组织。这次要记录的侧边导航就是sideNav.js这个模块。

页面效果

最终的效果如下图(如果有美丽说商家账号也可以直接访问该 链接 来看):

侧边导航栏

页面根据商品的不同属性信息划分为:在店铺的分类、款式/属性、标题/副标题/简述、货号/美丽制造货号、SKU设置、价格/库存、运费、图片信息和其他信息共8个大模块。其中图片信息模块下又分为封面图、产品介绍、商品细节、商品实拍、尺码说明、资质认证和店铺介绍工7个固定模块,以及可以动态添加或删除的自定义模块。现在侧边导航要实现的功能为:

  1. 点击侧边导航栏的不同选项,页面滚动到对应的功能区域。
  2. 根据页面当前滚动位置,高亮所在区域对应的侧边导航项;如果该项不在视野内,则滚动导航栏使该项移动至视野内。
  3. 点击添加或删除自定义模块后,能自动在导航栏中对应添加或删除对应导航项。
  4. 点击保存宝贝后,会进行信息校验;如果有错误,会在侧边导航中添加


阅读全文 »

使用 JavaScript 闭包实现 Google Maps 平滑缩放

注意:因本页面引用了 Google Maps 服务,建议翻 qiang 浏览,否则可能造成演示部分无法正常显示。

看书看得头晕,写篇博文放松下。刚才跑到 Google Maps 的 reference 看了下,发现好多 API 已经升级。想起去年自己实现的一个平滑缩放功能,现在做个总结记录一下。

问题描述

之前做项目要用到 Google Maps 的缩放功能,map 通过使用setZoom(level)方法来设置 map 的 zoom 值。level 通常为0至18之间的一个整数值。如果当前的 zoom 值和setZoom(level)中的 level 值相差不超过2时,地图会有一个渐变的缩放过程。当差值超过2时,地图会直接刷新到新的缩放程度,而没有渐变的动画过程。

解决方案

鉴于上面的特点,考虑当差值超过2时,分多次调用setZoom(level)方法,每次使得 level 的值增加2(当最后一次缩放程度为1时除外)。考虑到 JavaScript 是单进程的,所以使用闭包来实现这个功能,使用外部变量来存储每次缩放前后的 zoom 值。函数代码如下:

[crayon-662…
阅读全文 »