Latest stories

JavaScript async and Promise

非常推荐先看一下参考链接里两个 youtube 视频,分别介绍了 event loop 和 setTimeout 的实现原理,这对于理解 JavaScript 里异步操作实现非常有帮助。其次是关于 Promise object 的手动实现,有一些抽象,因为包含了大量的 callback 函数。这里一定要分清楚,哪些是函数的声明,哪些是函数的调用。

Event loop

JavaScript 是一种 single thread 的语言。既然单一线程,那么在某个时间点,只能完成一项任务。于是

$.get('http://twitter.com')
$.get('http://youtube.com')
$.get('http://google.com')

在单线程下,如果某一行执行所需要的时间太久了,那么余下的的 command 也无法执行,程序就在那一行停滞下来了。我们把这个叫做 blocking。然而事实上,当我们在使用 setTimeout() 函数时,程序似乎不会出现 blocking。

console.log('hi')
setTimeout(() => console.log('there'), 0)
console.log('Welcome!')

// output:
// hi
// Welcome
// there

这里哪怕是设置 delay 为 0s, setTimeout() 里的函数也是在最后才执行,是怎么回事呢?

在 JavaScript 的执行环境中,所有的需要运行的函数是单线程的,按照次序会出现在 call stack 里。而通常,JavaScript 要么在 Browser 里运行,要么在 Node 环境运行,在 Browser 里运行时,会有一整套来自 Browser 提供的 web API,同理在 node 环境里也有相应的 API。 setTimeout() 函数就来自这些提供的 API 中。当我们 declare and call 一个 setTimeout() 函数时,Browser 会生成一个 timer 计时器,计时器的时间达到时, setTimeout() 里定义的 callback 函数会进入到一个叫 task queue 的容器中,此时程序会去检测 call stack 是否为空,当 call stack 为空时,会将 task queue 中最上层的函数移入 call stack 中进行执行。因此本质上来讲,由于有 web API 的加持,最终类似 setTimeout() 函数还是使用了多线程。只不过对于 JavaScript 来讲,一直是执行的是 call stack 里的内容,可以认为一直是单线程操作。

赤烛 - 『还愿』

『还愿』这个游戏,从去年放出预告开始,我就有关注。去年 7 月释出先导预告,内容是几支 80 年代广告和一档童星选秀节目。随后又陆续释出一些图片,比如贴满广告的大门的照片。去看网上关于这些预告的分析,发现这里不免夹杂了凶杀、分尸、拜神、祭祀等等恐怖惊悚的「奇情」元素。这些内容会让人联想到『血观音』,会联想到 93 年的香港电影『人肉叉烧包』,或者是15 年翁子光导演执导的『踏血寻梅』。这类电影都可以归纳为「奇情片」的概念,它们往往会是一些凶杀案件,和普通的犯罪片不同,犯罪手段通常都是凶狠残忍,而且动机难以捉摸。

奇情电影的背后往往蕴含着对时局动荡、社会不稳定的一种本能性的恐惧。要么直接诉苦,要么转移视线。

『奇异的……』 Episode 32 - 硬影像

『还愿』同样是具有「奇情片」内核的恐怖游戏。

以下内容涉及剧透。

『还愿』的故事背景设定在 80 年代的台湾。故事的叙述在 1980 年,1985 年,1986 年三个时间点互相穿梭,交叉叙事。80 年代的台湾究竟发生了什么?1979 年末发生了轰动一时的「美丽岛事件」。

棋盘上的「古墓丽影」

又是一个新年过去了。在年复一年不变的习俗和渐渐消淡的年味里,我把 Lara Croft Go 打通了。在 Square Enix 的 Go 游戏三部曲里,Hitman Go 是几年前玩过的,去年尝试了 Deus Ex Go。相比之下,更喜欢这部 Lara Go。Deus 里的科幻风太过浓重,Hitman Go 很贴近现代都市,在棋盘模拟的场景里,有熟悉的游泳池,花园,房屋里的家具等等。Lara Go 的场景都是放在野外,山窟洞穴,悬崖峭壁。如果另外两作的特点都是在「潜入」,那么 Lara Go 的特点则是在「冒险」。尽管有着固定的棋盘,每次只能前进一格,但这的确是个不折不扣的 Tomb Raider 式的冒险故事。

![Lara Go 1](/images/Game/Lara Go 1.jpg)

游戏整体美术风格,偏向折纸,背景的黑色剪影提供沉浸感。这样的美术风格在 iOS 平台并不少见。熟悉的有「纪念碑谷」「Alto’s Odyssey」。这样偏折纸的艺术风格,也比较适合这样的游戏模式。Square Enix 在 Go 系列游戏里想做的,是希望把 Go 系列做成一种桌游类型的游戏,所以这样的折纸风格再完美不过了。几年前在玩 Hitman Go 时,每一关的地图,都是按照桌游的包装盒来设计的。

以下内容涉及剧透。

「User Authentication with Passport and Koa 」Summary

上周在阅读 Express.js Blueprints 时看到 Authentication 的部分,就想着使用 Koa 去复现一遍。于是在网上看到这篇文章 User Authentication with Passport and Koa 。文章给出了源代码和详细的步骤。其中不乏遇到自己不熟悉的知识领域,比如 knex,postgresql 和 redis 等等。写这篇文章的目的:一是熟悉下在 koa 框架下的程序结构;二是对于自己不熟悉的知识领域的一个总结。

需要通过 brew 安装:

  • postgresql
  • redis

使用 npm 全局安装:

  • knex

初见 Koa.js

去网上检索 Koa,往往会看到诸多 Koa 和 Express 文章。Koa 的确是比 Express 更新的框架,因此也使用到了 ES6 更新的特性,比如 async/await。Koa 的核心 module 仅仅是 middleware kernel,Express 则提供了一套完整的解决方案,功能,routing,template 这些。Koa 要使用这些需要安装额外的 module。这样的对比,容易让人联想到 editor 和 IDE 的区别,前者注重轻量,可定制,后者追求大而全的设计。两种不同的设计哲学,我是偏爱前者,相信 less is more 的力量。当然,毕竟 Koa 和 Express 都是来自于同一个开发团队,很多基础概念是相通的。阅读本文,你需要提前了解以下内容:

  • Node.js 的异步特性及异步是如何实现的
  • 异步实现的几种方式,callback 到 Promise 到 async/await
  • 什么是 middleware?
  • ejs template engine

通过本文,你能了解到。Koa 最基础的 HelloWorld,它 如何渲染一个 template 页面,传递数据。什么是「Routing 路由」,路由在 Koa 中如何实现的。

异步 & callback

最近开始学习 Node.js。主要看两本书:Node.js in PracticeNode.js Design Patterns。前者类似于 o’reilly 的 cookbook 系列,整本书的编排是通过一个个 recipe,一个个具体的 problem&solution 实现的。后者就是 Packt Publishing 出品的一系列 Design Patterns 书籍。包括这两本书在内的许多讲解 Node.js 的书籍,都会不断强调两个关键词, asynchronous 和 non-blocking I/O。在最初开始学习编程的时候,无论是写一些算法题目,或是做一些本地测试,它都是同步的,即时响应的,单线程的,blocking I/O。但如果进入的网络领域,「异步」则会被不断提起。相比 synchronous,「异步」更加接近我们相处的真实世界。

这篇文章以 Node.js Design Patterns 第二章的 Web Spider 例子,探究思考在 Node.js 中是如何通过 callback 来实现异步操作的。

Hexo Theme 开发不完全记录

决定建立一个静态 Blog,已经是 2016 年的事了。在那之前,也就是在 2016 年 4 月 5 日,自己曾经使用 Pelican 进行过短暂的尝试。生活在互联网时代,当你决定将一切电子化,义无反顾地投入比特的世界时,最大的好处便是,这以后发生的每一起事件,都有着清楚的记录。建立 Blog 这件事也不例外。但仅过 1 天,我就删除了 github 上的 repo。当时的自己这样写道:

两天的尝试发现:没有足够的知识积累,挑战就是「摸着石头过河」,到处都是困难,耐心被一点一点消磨,直到像一只无头苍蝇乱撞,而无法再耐心地解决问题。所以,博客平台搭建计划暂停。

那时自己才刚开始学 Python,也才刚开始接触 Github。其他方面更是经验甚少,处处碰壁。一年以后, 2017 年 3 月,自己使用 Hexo 建立了这个 Blog,并在 Godaddy 上购买了域名,采用 Hexo 预置主题 Next 。全面,简洁,美观大方。这个主题足够好用。当时的主题并不多,所以经常看到其他使用 Hexo 搭建的 Blog ,往往都是差不多的样式,我当时也只是改了以下 banner,才显得稍有不同。这也让我想试着自己去写一个主题。

目前看到的这个 theme 所有样式,并非我本人设计。它来自于一款付费的 WordPress theme typology。我是一次偶然的机会看到它。考虑到可能的版权问题。自己可能不会把它发布到 Themes | Hexo 或开源到 Github 上(无法联系到这个 theme 的作者)。以下我所做的大部分工作,不过是以 Hexo 的形式对 typology 的再现。为了方便。我把这个模仿之作命名为 hagoromo(羽衣)。至于为什么会叫这个名字,Google 会给你答案。

1/n- Cycle | 6kyu

Details

Let be n an integer prime with 10 e.g. 7.

1/7 = 0.142857 142857 142857 ....

We see that the decimal part has a cycle: 142857. The length of this cycle is 6. In the same way:

1/11 = 0.09 09 09 .... Cycle length is 2.

Task

Given an integer n (n > 1), the function cycle(n) returns the length of the cycle if n and 10 are coprimes, otherwise returns -1.

Exemples:

cycle(5) = -1
cycle(13) = 6 -> 0.076923 076923 0769
cycle(21) = 6 -> 0.047619 047619 0476
cycle(27) = 3 -> 0.037 037 037 037 0370
cycle(33) = 2 -> 0.03 03 03 03 03 03 03 03
cycle(37) = 3 -> 0.027 027 027 027 027 0
cycle(94) = -1 

cycle(22) = -1 since 1/22 ~ 0.0 45 45 45 45 ...

Note

  • Translators are welcome for all languages.

Lowest base system | 4kyu

要点

  • 除法,求余,因子
  • Number.MAX_SAFE_INTEGER
  • 二分法求方程根

Details

Your task is determine lowest number base system in which the input n (base 10), expressed in this number base system, is all 1 in its digit. See an example:

‘7’ in base 2 is ‘111’ - fits! answer is 2

‘21’ in base 2 is ‘10101’ - contains ‘0’ does not fit ‘21’ in base 3 is ‘210’ - contains ‘0’ and ‘2’ does not fit ‘21’ in base 4 is ‘111’ - contains only ‘1’ it fits! answer is 4

n is always less than Number.MAX_SAFE_INTEGER.

这个题目的难度主要在于性能 performance 方面,对于数值较小的数字,通常方法很容易计算,一旦涉及到九位十位往上的大数,一般的循环方法就会耗时很久。

@wraps | 6kyu

要点

  • decorator 装饰器用法
  • tryexceptelse control flow
  • getattr()setattr()
  • __dict__.update()

Details

Implement the functools.wraps decorator, which is used to preserve the name and docstring of a decorated function. Your decorator must not modify the behavior of the decorated function. Here’s an example :

def identity(func):
  @wraps(func)
  def wrapper(*args, **kwargs):
    """Wraps func"""
    return func(*args, **kwargs)
  return wrapper

@identity
def return_one():
  """Return one"""
  return 1

return_one.__name__ == 'return_one' # If wraps hadn't been used, __name__ would be equal to 'wrapper'
return_one.__doc__ == 'Return one' # If wraps hadn't been used, __doc__ would be equal to 'Wraps func'

Note: of course, you may not use the functools module for this kata.

题目要求,经过一次二重的装饰器,保留原来函数的 __name____doc__。二重装饰器 decorator,就是用一个 decorator 去 decorate 另一个 decorator。该二重装饰器装饰后的函数, 输出的是一重装饰器装饰过的函数,但是 __name____doc__ 得到保留,及为原函数的值。

依照题目给的例子,就是输出是被 decorator wraps 修饰过的 wrapper 函数,即函数主体和功能还是 wrapper,但因为被 wraps 装饰了,输出的 wrapper 函数的 __name____doc__ 值为原函数 return_one 的值。

分类

标签