本文翻译自 We have a problem with promises ,为原文题目重新起了一个题目并且对原文有删改。
各位 JavaScript 程序员,是时候承认了,我们在使用 promise 的时候,会写出许多有问题的 promise 代码。 当然并不是 promise 本身的问题,A+ spec 规范定义的 promise 非常棒。 在过去的几年中,笔者看到了很多程序员在调用 PouchDB 或者其他 promise 化的 API 时遇到了很多困难。这让笔者认识到,在 JavaScript 程序员之中,只有少数人是真正理解了 promise 规范的。如果这个事实让你难以接受,那么思考一下我在 Twitter 上出的题:
问:下面四个使用 promise 的语句之间的不同点在哪儿?
1 2 3 4 5 6 7 8 9 10 11 doSomething().then(function () { return doSomethingElse(); }); doSomethin().then(functiuoin () { doSomethingElse(); }); doSomething().then(doSomethingElse()); doSomething().then(doSomethingElse);
如果你知道这个问题的答案,那么恭喜你,你已经是一个 promise 大师并且可以直接关闭这个网页了。
但是对于不能回答这个问题的程序员中 99.9% 的人,别担心,你们不是少数派。没有人能够在笔者的 tweet 上完全正确的回答这个问题,而且对于 #3 最终答案也令我感到震惊,即便我是出题人。
答案在本文的底部,但是首先,笔者必须先探究一下 promise 为何如此复杂,为什么不管是新手还是专家都有被 promise 折磨的经历。同时,笔者也会给出自认为能够快速、准确理解 promise 的方法。而且笔者确信读过这篇文章之后,理解 promise 不会那么难了。
在此之前,我们先了解一下有关 promise 的一些常识。
阅读全部
我跟你说,我最讨厌“简介”这种文章了,要不是语文是体育老师教的,早就换标题了!
Decorators 是ECMAScript现在处于Stage 1 的一个提案。当然ECMAScript会有很多新的特性,特地介绍这一个是因为它能够在实际的编程中提供很大的帮助,甚至于改变不少功能的设计。
先说说怎么回事
如果光从概念上来介绍的话,官方是这么说的:
Decorators make it possible to annotate and modify classes and properties at design time.
我翻译一下:
装饰器让你可以在设计时对类和类的属性进行注解和修改。
什么鬼,说人话!
所以我们还是用一段代码来看一下好了:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 function memoize (target, key, descriptor ) { let cache = new Map (); let oldMethod = descriptor.value; descriptor.value = function (...args ) { let hash = args[0 ]; if (cache.has(hash)) { return cache.get(hash); } let value = oldMethod.apply(this , args); cache.set(hash, value); return value; }; } class Foo { @memoize; getFooById(id) { } }
别去试上面的代码,瞎写的,估计跑不起来就是了。这个代码的作用其实看函数的命名就能明白,我们要给Foo#getFooById
方法加一个缓存,缓存使用第一个参数作为对应的键。
可以看出来,上面代码的重点在于:
阅读全部
作为一个前端,不可避免同时与三个语言打交道:JS、CSS 和 HTML。而 HTML,超文本标记语言,是其中可编程性最弱的,一直以来得到的关注都较少。加上浏览器对 HTML 逆天的容错支持,即使是错误百出的文档也可以在浏览器里边表现得中规中矩。这样的背景下,绝大部分被产出的 HTML 代码都存在着各种各样的小问题,比如缺少必要的元信息(meta),比如混乱的 class、id 或属性的取值格式;这些问题或影响页面在不同浏览器下的表现,或增大了页面的开发、维护成本。
因此,选用一个合适的工具对 HTML 代码进行质量控制会是一件很有意义的事情。本文选择了 Bootlint、AriaLinter、htmllint、HTMLHint 及 htmlcs 这五个目前最活跃的相关项目进行对比。除此之外还存在如 tidy、W3C/Mozilla HTML validator 等工具,但它们专注于 HTML 规范,几乎不涉及代码风格上的检查,这里就不做比较。
对比角度将主要包括以下几个方面:
为了后续说明的便利,这里先对语法风格的规则进行简单的分类,第一类包括 attr-value-double-quotes
(使用双引号包围属性值), max-length
(限制单行最大长度), tag-pair
(要求需要显式闭合的标签显式闭合)等;第二类包括 script-in-tail
(JavaScript 内容要求在页面最后嵌入), title-required
(要求 title 标签), id-class-ad-disabled
(不允许在 id 或 class 的值中出现 ad_,ad-,_ad,-ad 等)等。这两类规则有很明显的区别,第一类偏重于代码格式(遵循与否都不影响最终语义),这里叫它格式规则;对应地,第二类偏重语义,即最终 document 的表现,这里叫它语义规则。一般情况下,前者更适合在语法分析阶段做,而后者更适合在分析完后基于分析结果(AST / document)进行。
阅读全部
前端模块化背景
在大部分单页式应用中,前端代码都是以 MV* 的结构来组织的,好处自然不必多说。在开始一个项目时,我们往往会将项目的业务功能纵向切分成多个子业务功能, 以模块的形式分配给团队各个开发人员,以达到最大的并行开发。随着业务的发展,新的项目也越来越多,我们会发现很多新的项目和现有的项目是有不少功能交集的。
从业务角度来看,一个项目就是由各个模块组合而成:A 项目由 m1, m2, m3 组合而成, B 项目则可能由 m1, m3, m4 组合而成。
在业务上将各个功能拆分明确后,很明显的 m1, m3 两个功能在 A 项目都是存在的,从工程角度来说,开发 B 项目的时候如果能够直接将A项目已经开发完毕的 m1, m3 直接复用, 那么必然是能够带来很明显的人力节约。
接下来就是从技术上去实现功能的复用,对于后端来说,通常的做法是服务化接口,而对于前端来说,我们目前的方案正是前端模块化:将功能打包为模块,发布至内部中央仓库, 使用方通过自己的方式(如:npm, bower, link[import], 百度的 edp, fis 等)导入模块包使用。
按照前端模块化的思路,开发新项目时,开发人员的工作从原来的开发所有功能变为:接入已有的功能模块,开发不存在的功能模块。
阅读全部
Content-Type
在开发 baidubce-sdk 的时候,遇到了在不同浏览器(主要是 Firefox 和 Chrome)下调用 xhr.setRequestHeader
设置 Request Header
之后,内部的处理逻辑有一些细微的差别,导致baidubce-sdk
无法正常的工作。
1 2 3 4 5 var xhr = new XMLHttpRequest();xhr.setRequestHeader('Content-Type' , 'foo/bar' ); xhr.open('POST' , '' , true ); xhr.send('' );
对于上面这段儿代码,因为我们显式的设置了Content-Type
,所以我们期望的是服务器收到的 Request Header
中 Content-Type
应该是 foo/bar
,实际上在 Firefox
里面会自动添加 charset=UTF-8
,也就是服务器得到的信息是 foo/bar; charset=UTF-8
阅读全部