Git是分布式版本控制系统,特别适合多人协作开发。2005年Linus用了10天时间,开发了第一版Git,用于管理linux内核的代码(from wiki)。GitHub是一个源代码托管服务平台,使用Git作为版本控制软件,2018年被微软收购。

Git内部会有一个Repository,给代码库做快照,每一次commit,都会把完整的代码库进行快照,并保存起来。

git config --global -e

git config --global user.name

git init

  • 初始化当前目录为代码库

git add .

  • 把新修改的文件放入stage area。stage area相当于一个缓冲区。

git commit [-m desc]

  • 把stage area的文件作为正式的代码提交,放到Repository中。
  • 如果不加-m,可以打开默认的编辑器,写比较长的commit描述

git status [-s]

  • 查看当前work tree,stage area,repository的情况,可以看到哪些代码做了变更,哪些准备commit
  • -s选项可以简化status的输出

git diff [--staged]

  • diff命令可以查看working dir和stage area中代码的区别
  • --staged选项,可以查看stage area和最后commit的代码的区别

git log --oneline

  • 查看代码库提交历史
  • --oneline选项可以简化输出

git show [commit id] [HEAD~n]:<filename>

  • 可以查看具体某次commit的时间,作者,修改的文件,和内容
  • 加上:<filename>可以看到在那次commit时,指定文件当时的内容

git restore

  • 可以把stage area的代码,拷贝回working dir,这样可以把代码复原
  • git restore --source=HEAD~2 <filename>可以把指定文件恢复到以前的某次提交

git rm [--cached] file

  • git rm 会删除repo、stage area,和work tree上的代码
  • 加上--cached,会保留工作区对应文件

git checkout

  • 可以切换到某一次commit
  • 可以切换到某一个tag

git tag

  • 对某一次commit打标签

git branch

  • 在当前HEAD的commit上,开分支
  • git branch -r,查看代码服务器上的分支

git switch [-C]

  • 可以切换branch
  • -C选项可以同时创建分支,并切换到此分支上
  • git switch -C local-branch origin/branch,可以切换到服务上的分支,继续开发

git merge

  • 合并分支,主要是把其他分支合并到master上
  • --abort可以中止merge,回到合并前

git clone

git fetch

  • 把remote repo的commit拉下来,需要手动merge

git pull

  • 把remote repo的commit拉下来,同时自动做merge

git push

  • 把本地的修改,push到服务器上
  • git push origin v0.1,这样可以推送tag,
  • git push origin --delete v0.1,删除服务端tag
  • git push origin --delete <branch name 删除服务端branch

Git接触也有近10年,原来一直用错了。之前都是用CVS,而且没有多人开发同一模块的情况,现在有多人开发一份代码的时候,有必要重学一遍Git。

Docker是一种类似虚拟机的容器,但是更轻量级,更方便。

他可以创建一个独立的环境,减少环境配置的工作。

Docker是2013年首次发布,是YC孵化的项目。

阅读全文 »

写CSS就是在写配置文件,到处充满了经验、技巧,要求对各种属性特别熟练。甚至很多地方是利用浏览器不完善边边角角,进而实现一些酷炫功能。

阅读全文 »

HTML和CSS,js是web开发必要的工具。但是他们之间关系很乱,HTML可以对内容进行标识,也能有默认样式,还具有一些功能,但是现在最主要的就是把页面的结构划分好,然后由CSS来呈现布局、样式,由js来响应用户操作。

但是就像那些大牛说的,HTML其实不是知识,也算是配置文件的一种,都是实施细节而已。但是因为应用APP涉及细节过多,几乎没法一个人单打独斗,这就是困境所在。

阅读全文 »

一、安装python

  1. 安装pyenv (https://github.com/pyenv/pyenv)

  2. 安装python 依赖库

  3. 切换python 版本

二、安装Flask

  1. 创建env

    python -m venv env --promot myenv

  2. pip install flask

四、修改nginx配置

  1. location / 转向gunicron
  2. 静态文件js, css, img,转到static目录

五、启动gunicron

nohup gunicorn --workers 3 --bind unix:web.sock app:app &

前端都是事件响应机制。发送个请求,返回结果后通过某个事件的回调函数处理。如果需要返回的数据太大,则需要一直等待。通过Stream,就能返回一部分,就解析一部分,显示一部分。可以优化体验。

fetch API返回的response.body是一个 ReadableStream对象。ReadableStream对请求大体积文件时非常有用,可以让应答数据,一小段一小段的解析。Web Stream应该是为网络视频,网络直播专门开放的API。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
// fetch函数是立刻返回一个promise,当HTTP Header的应答到来时,就进入then函数 
fetch(url).then((response) => {
// response.body是ReadableStream.
var reader = response.body.getReader();
var bytesReceived = 0;
return reader.read().then(function processResult(result) {
if (result.done) {
console.log("Fetch complete")
return
}
// result.value for fetch streams is a Uint8Array
bytesReceived += result.value.length
console.log("Received", bytesReceived, "bytes of data so far")
// Read some more, and call this function again
return reader.read().then(processResult)
})
})

这样就是通过对fetch取回的response.body,可以做流式处理,对视频,图片,大文件都有好处,至少能显示进度了。

也可以创建自定义的ReadableStream。ReadableStream在创建时,需要提供underlying source,就是数据源对象。在规范文档中,对source分为push source,和pull source。比如websocket属于push source,而读取文件算是pull source。在规范文档中都有例子。

1
2
3
4
5
6
7
8
var stream = new ReadableStream(
{
start(controller) {},
pull(controller) {},
cancel(reason) {},
},
queuingStrategy,
);

但是这里有几个地方值得注意,规范中貌似没有写清楚,这些内部机制不理解导致很多代码看不懂:

  1. start函数会立即执行
  2. pull函数会在start函数立即执行
  3. 如果start函数返回一个promise对象,则pull函数不再执行,而是等promise对象resolve以后才开始执行pull函数
  4. chunk data可以通过controller.enqueue放入ReadableStream的内部队列中,每次enqueue,都会触发pull函数
  5. 如果pull函数,返回一个promise,则不会每次enqueue都触发pull函数

在pdf.js的代码中,main线程和worker线程之间通过stream,传递pdf数据,很多利用了ReadableStream的特性,这些特性的教程很少。理解起来挺费劲。

优秀参考:

2016 - the year of web streams

Streams Living Standard

在Javascript中,函数被称为函数对象,就是可以把函数看成是一个某个类创建的实例对象,他可以有属性和方法,可以保存在数组中,可以做为参数传入其他函数,可以作为函数返回值。和其他对象的区别,主要在于函数对象可以被执行。

函数还可以这样写。通过new语句,new一个Function对象出来,把函数体作为字符串传入。

1
2
3
4
var body = "return Math.PI * radius * radius";
var circle = new Function("radius", body);

console.log(circle(5)); // => 78.5398..

这可能就是解释型语言的好处,可以把字符串变成可运行的代码,不需要像c语言那样,必须编译为二进制的机器语言才能执行。

Javascript单线程,同步执行的语言。早期只是简单处理静态数据,这没问题。但是后来越来越多需要js去访问网络,所以需要一种异步机制。于是有了很多非阻塞,依赖Event Loop的web api可以实现异步。但这种web api需要写很多callback函数。

但是callback层级一旦多了以后,代码变得不可读,不可维护,于是ES6就给出Promise的异步方案

Promise
1
2
3
4
5
6
7
8
9
10
11

function executor(resolveFunc, rejectFunc) {
setTimeout(() => resolveFunc(1), 1000); // (*)
}


function handleResult(resp) { // (**)
console.log(resp)
}

new Promise(executor).then(handleResult)

Promise可以看成是一个类,他生成的对象可以在未来把异步操作的结果返回回来。他实现了callback相同的功能,但包含了新特性,而且有更具可读性的语法。很多Web API实际上就是返回一个Promise对象。

Promise通过new语法生成一个包含状态和结果的对象。创建对象时,需要传入一个函数,就是那个耗时的函数,这个函数需要有两个参数,分别表示成功和失败后的操作,这两个函数resolve,reject是Promise提供,只需要在executor中正确调用即可。

Promise对象通过.then()来绑定一个结果处理函数,当Promise对象已经resolve的时候,在then()登记的函数就会被执行,内部是通过MicroQueue实现的。then()函数把resolve收到的参数,传给handleRequest来处理。

很多WebAPI返回的就是Promise对象,所以不需要自己去new,只需要好好处理then()就可以了,比如fetch API。

1
2
3
4
5
6
7
8
9
10
11
// Fetch a user from the GitHub API
fetch('https://api.github.com/users')
.then((response) => {
return response.json()
})
.then((data) => {
console.log(data)
})
.catch((error) => {
console.error(error)
})
Async/Await

Promise的好处就是去掉了callback嵌套,但是还是把代码分成了两块。ES7又提出async和await关键字。

通过async可以把普通函数变成异步函数,就是就是把这个函数当做executor放到一个Promise对象里面,然后返回一个Promise对象。

1
2
3
async function myFunction() {
// 这是一个异步函数
}

在异步函数中,你可以在调用一个返回 Promise 的函数之前使用 await 关键字。这使得代码在该点上等待,直到 Promise 被完成,这时 Promise 的响应被当作返回值,或者被拒绝的响应被作为错误抛出。

  1. async可以把普通函数变成异步函数,返回值是一个promise
  2. 加了async后,想获得函数的返回值,必须通过.then()语句
  3. 在async函数中,可以使用await。await只能在async函数中使用
  4. 通过使用await,相当于代码一直同步等到异步API返回值以后,代码再继续运行。或者说通过await,避免了.then()的链式调用

js事件机制,其实是浏览器事件机制。毕竟JS是处理UI部分的语言,主要得依靠浏览器提供的能力,遵循浏览器的机制。

通过document.querySelector获得一个页面元素,可能是个button,或者是个form,div等。为他们绑定一个事件处理函数,通过obj.addEventListener就可以为指定的时间添加处理函数。

阅读全文 »

昨天听了keep从0到1的产品分享。产品从0到1是对认知的考验,不是对产品的考验。什么认知呢?就是对用户需求的认知。通过产品来验证,最开始的假设是否是正确的。

需求是用户的问题,问题是理想和现实之间的差距。

阅读全文 »
0%