讲讲 Promise

一、什么是 Promise

1.1 Promise 的前世今生

Promise 最早出现在 1988 年,由 Barbara LiskovLiuba Shrira 首创(论文:Promises: Linguistic Support for Efficient Asynchronous Procedure Calls in Distributed Systems)。并且在语言 MultiLispConcurrent Prolog 中已经有了类似的实现。

JavaScript 中,Promise 的流行是得益于 jQuery 的方法 jQuery.Deferred(),其他也有一些更精简独立的 Promise 库,例如:QWhenBluebird

# Q / 2010
import Q from 'q'

function wantOdd () {
    const defer = Q.defer()
    const num = Math.floor(Math.random() * 10)
    if (num % 2) {
        defer.resolve(num)
    } else {
        defer.reject(num)
    }
    return defer.promise
}

wantOdd()
    .then(num => {
        log(`Success: ${num} is odd.`) // Success: 7 is odd.
    })
    .catch(num => {
        log(`Fail: ${num} is not odd.`)
    })

由于 jQuery 并没有严格按照规范来制定接口,促使了官方对 Promise 的实现标准进行了一系列重要的澄清,该实现规范被命名为 Promise/A+。后来 ES6(也叫 ES2015,2015 年 6 月正式发布)也在 Promise/A+ 的标准上官方实现了一个 Promise 接口。

new Promise( function(resolve, reject) {...} /* 执行器 */  );

想要实现一个 Promise,必须要遵循如下规则:

  1. Promise 是一个提供符合标准then() 方法的对象。
  2. 初始状态是 pending,能够转换成 fulfilledrejected 状态。
  3. 一旦 fulfilledrejected 状态确定,再也不能转换成其他状态。
  4. 一旦状态确定,必须要返回一个值,并且这个值是不可修改的。

“讲讲 Promise”继续阅读

记一次 MySQL 崩溃的修复经历

这一天网站突然打不开报 MySQL 连接错误,上服务器后发现 MySQL 已经停止服务,各种启动无效。经历了一系列搜索和无效的工作后,去云服务上后台看监控,发现硬盘满了。于是得出结论硬盘空间不足会导致 MySQL 服务停止。

切到根目录下使用 du -sh * 查看各目录的占用情况,发现 /root/.pm2 在捣鬼。

20K    dump.pm2
16K    dump.pm2.bak
33G    logs
4.0K    module_conf.json
4.0K    modules
8.0K    pids
16G    pm2.log
4.0K    pm2.pid
0    pub.sock
0    reload.lock
0    rpc.sock
4.0K    touch

于是先删除日志文件,启动 MySQL 服务即可。

rm -rf logs/*
rm -rf pm2.log
service mysqld start

查看错误日志发现 Node 服务的某个模块不存在…

使用 Gulp 快速打包项目

一、安装

npm install --save-dev gulp gulp-cli

二、创建配置文件 gulpfile.js

定义 Gulp 任务,从而使用 gulp ${taskName} 来运行他。

# npm pkg
npm install --save-dev gulp-uglify

# gulpfile.js
const gulp = require('gulp');
const uglify = require('gulp-uglify');

gulp.task('build', function () {
  return gulp
    .src('./src/index.js')
    .pipe(uglify())
    .pipe(gulp.dest('lib'));
});

# >_
npx gulp build

gulp.task() 定义任务名字。gulp.src() 方法存放源文件(本例 ./src/index.js),如果要处理多个文件要写成数组形式:gulp.src(['1.js', '2.js'])。通过管道 .pipe() 内的方法进行处理这些文件,最后通过 gulp.dest() 保存修改过的文件。

“使用 Gulp 快速打包项目”继续阅读

使用 peerDependencies 缩减项目体积

一、什么是 peerDependencies

peerDependencies 存在于 NPMpackage.json 中,如果项目中依赖模块 X、模块 Y,模块 Y 又依赖模块 X,当模块 X 出现版本冲突的时候,则会打包出 X 的两份代码。在这个模块 Y 里面使用 peerDependencies 引入模块 X,这样当前项目和模块 Y 便会共用这个模块 X。

当在 peerDependencies 引入一个模块后:

  1. 当前的代码将与符合版本条件的模块和谐相处。
  2. 如何这个模块已经存在于项目的 node_modules 中,什么也不提示。
  3. 如何这个模块不存在于项目的 node_modules 中,警告用户缺少此模块,但是不自动安装。

注意: npm i 并不会自动安装 peerDependencies 里的模块,所以开发模块的需要在 devDependencies 同步添加相应模块。

二、什么场景下适合引入 peerDependencies

  1. 多份模块代码的重复加载易引发冲突。
  2. 依赖在项目中是可见的。
  3. 可以让开发者自己决定安装哪个版本。

“使用 peerDependencies 缩减项目体积”继续阅读

使用 requestIdleCallback 优化埋点数据上报

一、什么是 requestIdleCallback

requestIdleCallback 接收回调函数,在浏览器的空闲时段调用,这样既不阻塞关键性事件,又能保证低优任务的时效性。

二、使用 requestIdleCallback

可以像使用 setTimeout 一样使用 requestIdleCallback,区别是 requestIdleCallback 中的回调函数可以接收当前剩余空闲时间,以便合理利用这段时间来处理队列任务。一般会在回调函数内再次调用 requestIdleCallback,以便在下次空闲时间段继续执行剩余的任务。

“使用 requestIdleCallback 优化埋点数据上报”继续阅读

如何用 Sass/Less 实现单位转换(px to rem/em/vw)

移动端开发中,常常需要根据 UI 的设计稿做出适配移动端的网页,然而设计稿常常是以像素(px)为单位的,于是需要利用 CSS 预编译器 Sass / Less 来进行转化。

一、Sass

Sass 拥有类似于传统编程语言的函数 @function,可以接收参数并返回值。

“如何用 Sass/Less 实现单位转换(px to rem/em/vw)”继续阅读

实现 new

正常 new 一个实例:

# 场景一
function foo () {
    this.a = 1
}
foo.prototype.b = 2
const bar = new foo()
console.log(bar) // {a: 1}
console.log(bar.b) // 2

# 场景二 构造函数返回一个对象
function foo () {
    this.a = 1
    return {a: 2}
}
const bar = new foo()
console.log(bar) // {a: 2}

“实现 new”继续阅读