• 博文
  • 归档
  • hexo博客

    2018-11-26

    次访问

    基本操作

    写博客

    1
    hexo new 博客标题

    本地服务

    1
    hexo serve

    serve

    构建并发布

    1
    hexo g -d // hexo generate --deploy的简写

    版本控制与持续集成

    使用了上面的构建并发布流程后,你一定会觉得这个过程很麻烦,而且源文件不方便管理,虽然可以开一个分支放源文件,但还是很麻烦对不对?下面来看一个更好的处理办法,新的push出现时自动构建并发布:
    1、Content Repo:Hexo生成出来的静态网站放到GitHub Pages时用到的repo;
    2、Source Repo:hexo源文件的repo;
    3、使用CI工具(比如AppVeyor官网)来完成下面的功能:
    当有新的change push到Source Repo时,自动执行CI脚本,生成最新的静态网站发布到Content Repo。

    使用AppVeyor来建立CI的方法参考本文第二个参考链接。

    个性化

    文章链接

    更改_config.yml中的下列配置:

    1
    permalink: :category/:title/

    图片资源处理

    放在 source/images 文件夹中。然后通过 ![](/images/image.jpg) 的方法访问它们。

    1
    ![hexo serve](/img/serve.png) // 上面hexo serve的图片写法

    参考

    • 文档 | Hexo
    • Hexo的版本控制与持续集成 | formulahendry
    ...more
  • git常用操作

    2018-11-23

    次访问

    下载

    下载git bash
    下载meld

    基础配置

    新建.gitconfig和meld.sh文件放到C:\Users\win

    .gitconfig文件内容如下:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    [user]
    email = youremail@xxx.xx
    name = yourname
    [gui]
    encoding = UTF-8
    [core]
    autocrlf = true
    [color]
    ui = auto
    [branch]
    autosetuprebase = always
    [alias]
    st = status
    ci = commit
    co = checkout
    br = branch
    rb = reset --hard ORIG_HEAD
    unstage = reset HEAD
    lg = log --graph --oneline --decorate
    last = log --graph --oneline --decorate origin/master..HEAD
    [merge]
    tool = meld
    [diff]
    external = C:/Users/win/meld.sh

    meld.sh文件内容如下:

    1
    2
    #!/bin/sh
    meld $2 $5

    升级配置

    设置SSH Key

    1
    2
    3
    4
    5
    6
    7
    8
    9
    #生成公钥
    ssh-keygen -t rsa -C "youremail@xxx.xx"

    #查看公钥(复制公钥后到git仓库公钥管理页面添加key)
    cat ~/.ssh/id_rsa.pub

    #验证是否添加成功
    ssh -T git@xxx.xxx.xxx
    #Welcome to GitLab, xx! // 成功会出现这行欢迎

    多个ssh-key的管理

    假设你已经完成了上面的步骤,现在要给github添加一个用户和ssh-key。

    1
    2
    #生成公钥
    ssh-keygen -t rsa -C "youremail@gmail.com"

    现在进入.ssh目录,比如我的电脑用户名是win,我的目录就是C:\Users\win.ssh,把刚刚生成的id_rsa_github和id_rsa_github.pub都放进来。
    新建config文件,内容如下:

    1
    2
    3
    4
    5
    Host github.com
    HostName github.com
    IdentityFile C:\\Users\\win\\.ssh\\id_rsa_github
    PreferredAuthentications publickey
    User youremail@gmail.com

    现在.ssh目录结构如下:ssh

    现在本地都配置完毕,去github添加刚刚生成的id_rsa_github.pub。然后验证ssh-key是否都添加成功。

    因为有多个用户了,上面的.gitconfig全局配置了用户信息。那么在特殊项目,就需要局部设置用户信息:

    1
    2
    3
    4
    #局部配置,优先使用局部配置,如果没有局部配置,默认用全局配置
    cd ~/workspace/github_project/
    git config user.name 'yourename'
    git config user.email 'youremail@gmail.com'

    解决LF和CRLF问题

    推荐使用方法2。

    1、.gitconfig文件里的autocrlf设置为true

    true会在git commit的时候自动把commit的内容里的CRLF转成LF,保证远端代码都是LF

    2、vscode用户,在USER SETTINGS里增加配置项”files.eol”: “\n”

    files.eol配置项含义:The default end of line character. Use \n for LF and \r\n for CRLF.

    3、vscode安装插件,保存是自动转换成LF。比如EditorConfig for VS Code.

    统一commit message格式

    根据 angular 规范提交 commit, 这样 history 看起来更加清晰,还可以自动生成 changelog。

    提交 commit 的类型,包括以下几种:

    • feat: 新功能
    • fix: 修复问题
    • docs: 修改文档
    • style: 修改代码格式(空格、换行、分号等),不影响代码逻辑
    • refactor: 重构代码(既不是修复bug,也不是增加新特性),理论上不影响现有功能
    • perf: 提升性能
    • test: 增加修改测试用例
    • chore: 修改工具相关(包括但不限于文档、代码生成等)
    • deps: 升级依赖,修改版本号

    还可以借助插件来写符合规范的message:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    # Making your repo Commitizen-friendly
    # For this example, we'll be setting up our repo to use AngularJS's commit message convention also known as conventional-changelog.
    # First, install the Commitizen cli tools:
    npm install commitizen -g

    # Next, initialize your project to use the cz-conventional-changelog adapter by typing:
    commitizen init cz-conventional-changelog --save-dev --save-exact

    # commit codes(use git cz to instead git commit)
    # For detailed explanation on how things work, checkout the [guide](https://github.com/commitizen/cz-cli).
    git cz

    常用命令

    基础操作

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    # init
    git clone git@git.xxx.xx:xx/xxx.git

    # add codes
    git add

    # push codes
    git push origin feature-name

    # new branch
    git checkout master
    git checkout -b feature-new

    # merge branches(use rebase to instead merge)
    # For example, merge feature-new to master(please make master up-to-date with 'origin/master' at first)
    git checkout feature-new
    git rebase master
    git checkout master
    git rebase feature-new

    tag

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    #新建标签
    git tag v1.0 // 打在最近的commit上
    git tag v0.9 f52c633 // 打在f52c633上
    git tag -a v0.9 -m "blablabla..." // 指定标签信息

    #查看标签
    git tag // 查看所有标签
    git show v0.9 // 查看单个标签,可以看到标签信息

    #删除标签
    git tag -d v0.1 //删除本地标签
    git push origin :refs/tags/v0.1 //删除远程标签

    #推送标签
    git push origin v1.0 // 推送单个标签
    git push origin --tags // 推送所有标签
    ...more
  • Promise总结

    2018-10-15

    次访问

    Promise简介

    Promise对象用于表示一个异步操作的最终状态(完成或失败),以及其返回的值。由浏览器直接支持。

    打开Chrome的控制台输入new Promise(function () {});后可以看到浏览器的Promise对象:promise

    下面创建一个Promise:

    1
    2
    3
    let promise = new Promise(function(resolve, reject) {
    // executor (the producing code, "singer")
    });

    传给new Promise作为参数的函数叫做executor。Promise创建后自动运行。

    promise有两个内部变量:
    1、state — 初始值pending, 会变成fulfilled或rejected。
    2、result — 初始值undefined,代码运行后的任意值。

    当executor运作完毕,会执行它两个参数中的一个函数:

    resolve(value) - 代表executor运作结果是成功的,并且:
    1、把state变成fulfilled;
    2、把result变成value。
    reject(error) - 代表executor运作出错,并且:
    1、把state变成rejected;
    2、把result变成error。

    promise-resolve-reject

    Promise状态是resolved或rejected时叫做settled。

    上面说到executor运行完毕会执行resolve或reject,其实executor只会执行一次resolve或reject,并且result改变后不能再改变。resolve/reject只会接收1个参数,后续的都会被忽略。

    1
    2
    3
    4
    5
    6
    let promise = new Promise(function(resolve, reject) {
    resolve("done");

    reject(new Error("…")); // ignored
    setTimeout(() => resolve("…")); // ignored
    });
    reject的参数推荐使用Error对象。

    demo

    1、处理 rejection

    有两种方式去处理 rejection

    1
    2
    3
    4
    5
    6
    let promise = new Promise((resolve, reject) => {
    setTimeout(() => reject(new Error("Whoops!")), 1000);
    });

    // .catch(f) is the same as promise.then(null, f)
    promise.catch(alert); // shows "Error: Whoops!" after 1 second
    .catch(f) 只是 .then(null, f)的简写。
    1
    2
    3
    4
    5
    // 方式一
    promise.then(f1, f2);

    // 方式二
    promise.then(f1).catch(f2);
    注意方式一和二的不同:f1发生的错误只会在方式二的catch中处理。

    2、Unhandled rejections

    发生错误时,Promise状态变成reject,execution跳转到最近的rejection handler,如果没有rejection handler,错误就会变成stuck。
    比如:

    1
    2
    3
    4
    5
    new Promise(function() {
    noSuchFunction(); // Error here (no such function)
    }); // no .catch attached

    // catch ReferenceError: b is not defined

    或者:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    // a chain of promises without .catch at the end
    new Promise(function() {
    throw new Error("Whoops!");
    }).then(function() {
    // ...something...
    }).then(function() {
    // ...something else...
    }).then(function() {
    // ...but no catch after it!
    });

    大多数js引擎会全局处理这种错误,我们可以在console中看到。

    要尽量避免出现Unhandled rejections,可以在promise调用链末尾增加catch。

    3、触发Promise异常

    • 主动调用 reject 方法
    • 抛出异常(exception)
    1
    2
    3
    4
    5
    6
    7
    new Promise((resolve, reject) => {
    a = b;
    }).catch((val) => {
    console.log('catch', val);
    })

    // catch ReferenceError: b is not defined

    4、链式调用

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    new Promise((resolve, reject) => {
    setTimeout(() => {
    resolve('成功1');
    }, 1000);
    }).then((val) => {
    console.log('then1', val);
    return '成功2'
    }).then((val) => {
    console.log('then2', val);
    return Promise.resolve('成功3')
    }).then((val) => {
    console.log('then3', val);
    return '成功4'
    })

    // then1 成功1
    // then2 成功2
    // then3 成功3
    注意then的返回值,链式调用时,前一个then的返回值决定后一个then的val。 通常而言,如果你不知道一个值是否是Promise对象,使用Promise.resolve(value) 来返回一个Promise对象,这样就能将该value以Promise对象形式使用。

    5、.then/.catch是异步的

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    console.log('javascript start');
    setTimeout(() => {
    console.log('setTimeout');
    }, 0);
    new Promise((resolve) => {
    console.log('promise1');
    resolve();
    }).then(() => {
    console.log('promise2');
    });
    console.log('javascript end');

    // javascript start
    // promise1
    // javascript end
    // promise2
    // setTimeout
    1
    2
    3
    4
    5
    6
    7
    8
    9
    new Promise((resolve) => {
    console.log('a')
    resolve('b')
    console.log('c')
    }).then((data) => {
    console.log(data)
    })

    // a c b

    构造函数中的executor执行是同步的,输出 a, 执行 resolve 函数,将 Promise 对象状态置为 resolved,输出 c。同时注册这个 Promise 对象的回调 then 函数。整个脚本执行完,stack 清空。event loop 检查到 stack 为空,再检查 microtask 队列中是否有任务,发现了 Promise 对象的 then 回调函数产生的 microtask,推入 stack,执行。输出 b,event loop的列队为空,stack 为空,脚本执行完毕。

    microtask:在当前 task 执行完,准备进行 I/O,repaint,redraw 等原生操作之前,需要执行一些低延迟的异步操作(microtask),使得浏览器渲染和原生运算变得更加流畅。假如每执行一个异步操作都要重新生成一个 task,将提高宿主平台的负担和响应时间。所以,需要有一个概念,在进行下一个 task 之前,将当前 task 生成的低延迟的,与下一个 task 无关的异步操作执行完,这就是 microtask。

    原生的setTimeout就算是将延迟设置为 0 也会有 4 ms 的延迟,会将一个完整的 task 放进队列延迟执行,而且每个 task 之间会进行渲染等原生操作。

    Promise 所说的异步执行,只是将 Promise 构造函数中 resolve,reject 方法和注册的 callback 转化为 eventLoop的 microtask/Promise Job,并放到 Event Loop 队列中等待执行,也就是Javascript单线程中的“异步执行”。

    Promise实现原理

    自行阅读参考的后3个链接

    参考

    • Promise - JavaScript | MDN
    • Promises, async/await
    • Promises/A+
    • 剖析Promise内部结构,一步一步实现一个完整的、能通过所有Test case的Promise类 · Issue #3 · xieranmaya/blog
    • 写一个符合 Promises/A+ 规范并可配合 ES7 async/await 使用的 Promise - 知乎
    ...more
  • Markdown常用语法手册

    2018-10-12

    次访问

    常用语法

    1. 斜体和粗体

    这是 斜体,这是 粗体。

    2. 分级标题

    在行首加井号表示不同级别的标题 (H1-H6),例如:## H2, ### H3

    3. 外链

    这是去往 本人博客 的链接。

    4. 无序列表

    • 无序列表项 一
    • 无序列表项 二

    5. 有序列表

    1. 有序列表项 一
    2. 有序列表项 二

    6. 文字引用

    • 整理知识,学习笔记
    • 发布日记,杂文,所见所想

    野火烧不尽,春风吹又生。

    野火烧不尽,春风吹又生。

    7. 行内代码块

    让我们聊聊 html。

    8. 代码块

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    /**
    * nth element in the fibonacci series.
    * @param n >= 0
    * @return the nth element, >= 0.
    */
    function fib(n) {
    var a = 1, b = 1;
    var tmp;
    while (--n >= 0) {
    tmp = a;
    a += b;
    b = tmp;
    }
    return a;
    }

    9. 插入图像

    我的头像

    10. 删除线

    这是一段错误的文本。

    11. 绘制表格

    Syntax Description
    Header Title
    Paragraph Text

    使用:对齐

    Syntax Description Test Text
    Header Title Here’s this
    Paragraph Text And more

    参考文档

    Markdown 语法速查表

    ...more

分类归档

  • ai3
  • css2
  • doc2
  • git1
  • js15
  • node2
  • 动效6
  • 图像处理13

标签云

最近文章

  • js遍历那些事儿
  • 详解CSS Grid布局
  • Shutterstock Editor关于Canvas和WebGL图片滤镜的实现
  • javascript异步error
  • win10编译opencvjs
PREV

© 2018 - 2024 Lovelyun