0%

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

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

Read more »

一、安装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就可以为指定的时间添加处理函数。

Read more »

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

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

Read more »

创业idea的常见错误

  1. 错误的认为要有一个很棒的idea

Google和Fackbook现在看起来都是很伟大的创意,但这都是事后诸葛亮。Google刚启动的时候,只是第20个搜索引擎。Fackbook刚启动时候,只是第20个社交网络。不是因为出色的idea使他们成功。他们的成功,是因为一个足够好的想法,加上非常棒的执行力。

  1. 刚有想法就立刻投入,而不去评估idea是否值得做

创业idea要花费好几年的生命去实现,应该花几周时间去认真思考这个想法是否值得做。至少应该认真做下调研,评估一下这个idea的价值。创业idea也是根据实际情况会变化的。如果启动点非常好,即使idea不是特别正确,根据用户反馈,idea也会慢慢调整正确。但是如果idea选错了,那就要重新开始了。

  1. idea是个解决方案,而是没有解决问题

单纯的把已成功业务模式放到另外一个行业中,很可能这个业务模式并没有解决这个行业中的任何问题,比如“滴滴修锁”。最好是从一个问题开始启动创业。而不是从一个解决方案开始,然后在寻找问题。

  1. 错误的认为创业idea很难找到

现实世界中有很多问题没有解决。通过学习一些好的创业idea,就能学会如何发现身边长期没有解决的问题。

以下几点可以评估一个创业idea是否好

  1. 要是个大生意

  2. 创始人要在此行业,有足够的专业知识

  3. 创始人要对这个idea,有新的,重要的insight。也就是说要有新的认知

  4. 最好这个问题,是创始人本人的问题

  5. 最近发生的变化(比如新技术),才使得这个问题有可能被解决

妨碍产生idea的过滤器

  1. 好像很难实现。厌恶性盲区(schlep blindness)

那些很麻烦,而且很难的事情,往往是正确的事情。不要因为难,就把一个想法给拒绝掉。恐惧会使野心勃勃的想法价值翻倍。当你决定实现一个雄大的想法时,你的竞争会更少,因为其他人会惊恐于这样大的挑战。把自己放到情景外。与其问“我需要解决哪些问题?”,不如问“我希望别人能为我解决什么问题?”(http://paulgraham.com/schlep.html)

  1. 无聊的事情

无聊的事情,很多人都不愿意干,反而是很好的创业机会。

  1. 好像事情过大了

选择难的事情,就会没有竞争对手了。容易的创业,启动比较轻松,但是成功却很难。(https://blog.samaltman.com/hard-startups)

  1. 羞于进入已经有很多竞争对手的行业

比较理想的市场是,已经有很多竞争对手了,但是创始人发现了所有人都没注意到的需求。

如何找到好的创业idea

越是坐在那冥思苦想,想出来的idea,越不靠谱,而自然而然地冒出来的创业想法,实际上很可能是好的。

可能产生idea的几个考虑点:

  1. 有哪些事是自己擅长的
  2. 想要别人为你解决什么问题
  3. 想一下,你最有激情的事情是什么?
  4. 想一下,世界上最近发生的变化有哪些?有哪些新的科技,新的平台,新的政策,新的问题
  5. 找一下最近成功的公司?看看能否做一些变种出来
  6. 问一下其他人有什么问题特别想解决的

要从需求角度看问题,看机会。 无论技术升级,产品功能升级,UI优化,流程简化,推广渠道变化,商业模式变化,都会带来新产品。但是成功的产品都有一个共性的特征,就是满足了之前尚未满足好的需求。通过满足了很小的需求,切入市场,形成壁垒,至少可以获得几年不错的利润。

Read more »