kindle电子书下载

2020年马上就要过去了,很多事情已经变化,很多网站也没法访问了。这里总结一下能下载kindle的网站吧。

https://salttiger.com/

http://cn.epubee.com/books/

https://www.aibooks.club/

https://new.shuge.org/

https://www.enjing.com/

https://www.aixdzs.com/

https://b-ok.asia/

http://kgbook.com/

https://www.iamtxt.com/

http://gen.lib.rus.ec/

http://www.haodoo.net/

https://sobooks.cc/

https://ebook.ipfs-lab.com/

https://ebook2.lorefree.com/

JS Promise迷思- 比较return Promise.resolve(val) 和return val

最近碰到这样一个问题,JavaScript可以通过Promise.resolve()来转化一个值或者thenable对象成为一个Promise。

Promise可以通过then串联起来(chain),then的函数中,可以直接return val,也可以return Promise.resolve(val),那么这两种方式有什么区别么?

我听到的回答是没什么不同,但是我理解不深,所以打算自己研究一下。构造以下代码例子,猜猜运行结果是什么呢?

Promise.resolve(1)
    .then(v => Promise.resolve(v + 1))
    .then(v => Promise.resolve(v + 3))
    .then(v => console.log(`First: ${v}`));
Promise.resolve(1)
    .then(v => v + 1)
    .then(v => Promise.resolve(v + 5))
    .then(v => console.log(`Second: ${v}`));
Promise.resolve(1)
    .then(v => v + 1)
    .then(v => v + 7)
    .then(v => console.log(`Third: ${v}`));

根据我对并发asynchronous的理解,如果这两种形式一样的话,结果有可能是顺序的First,Second,Third。也有可能是乱序的,First Second Third顺序不一定,在浏览器运行有可能因为某种原因,一直出现同样的结果,所以我们分别试试Chrome和Safari的操作台。但是结果很一致,哪怕在本地node直接跑nodejs也是一样。

结论是什么呢?return Promise.resolve(val)和return val这两种方式在结果上是一样的,对于不关注运行顺序的代码来说效果也是一样的。但对于开发人员来说,需要知道这两种方式的运行时间点是不同的,这个不同在某些复杂情况下需要考虑到。简单的说,如果不是故意要延迟结果的产生返回,return val这种方式既简单又快捷,用它就好了。

BTW。

参考这篇SO回答https://stackoverflow.com/questions/58217603/what-is-the-difference-between-returned-promise 以及这一篇https://dev.to/deepal/promises-next-ticks-and-immediates-nodejs-event-loop-part-3-2f57 可以知道Promise.resolve是一种微任务。

我大概能理解开发人员对于这些名词的怨念,微任务(microtask)又是什么?参考MDN这篇文章https://developer.mozilla.org/en-US/docs/Web/API/HTML_DOM_API/Microtask_guide 大概就是如下图所示。一个task完成以后,开始查询微任务队列microtask queue然后运行,接着运行下一个任务或者开始render。

这些内容有些高阶了,但对于JavaScript框架作者来说是必须的,想写框架的,可以参考这一篇https://blog.risingstack.com/writing-a-javascript-framework-execution-timing-beyond-settimeout/

(又一个)一行代码导致的血案-“is-promise”问题的粗浅分析

(Updated)开发者自己做了一个事后分析,比我讲的清晰多了,当然主要原因还是JS module依赖设计的复杂度https://medium.com/javascript-in-plain-english/is-promise-post-mortem-cab807f18dcc 在这一点上我很看好deno这个新工具。

——————————-

看到微信群里有人转关于“is-promise”更新导致的问题,公众号文章说的非常夸张,但又语焉不详,看了毫无头绪。于是看了些英文文章,做了点技术分析。

首先声明,因为水平不够理解不深,这篇文章并没有解释清楚问题的原因,只是说了一下我看到的现象,确保将来写类似代码的时候,心里有点谱。

“is-promise“有问题的版本更新是2.2.0,看了更新diff没发现什么明显问题。更新的目的主要是增加ES module风格的默认import。

首先得熟悉一下ES Module的import,还有commonjs的require。

先说一下ES6标准化的module,在浏览器中可以通过<script type=”module”>导入模块脚本,代码是这样的:”import xxx from ‘module-name'”。如果用CommonJS呢,就是“const package = require(‘module-name’)”。

在Nodejs v12之前使用的是commonjs,在v12的时候引入了ES Module的支持。在node中可以通过条件导入同时支持两种方式(麻烦!)https://nodejs.org/dist/latest-v12.x/docs/api/esm.html#esm_conditional_exports

在nodejs的官方文档中https://nodejs.org/dist/latest-v12.x/docs/api/esm.html#esm_dual_commonjs_es_module_packages 特意解释了双模式package的问题,其中特意提到了“Dual Package Hazard”(双Package风险),说实话这部分有些复杂,我也没有太理解。在后面提到了“Differences Between ES Modules and CommonJS“,其中第一条就是”Mandatory file extensions“,但是文档说的还是不清不楚的。

我们看一下is-promise的bug fix能理解更深一些。https://github.com/then/is-promise/commit/0b69f52ee73c9f6ad4480f02c9bccb14d2038656 可以看到主要就是对文件路径指定,变成使用”./xxx.js”方式。为什么原来有问题,现在就能fix,说实话我还是没看懂。我在本地做了一个极为简单的node js脚本文件,引入了is-promise 2.2.0版本,尝试了import和require两种方式,没发现有问题。我也尝试从bug report中找点线索,但是大多数都是说xxx有问题了,没有细节。我甚至到create-react-app中查找is-promise,根本就没有,简直是磕了。

先这样吧,等我理解更多了再更新此文。

另外在HN上关于这件事的讨论https://news.ycombinator.com/item?id=22979245 也是非常热烈,不过没人分析原因,要么吐槽,要么建议用npm指定版本方式(版本号不用^和~)。

async/await仅仅是promise的语法糖么?

简单的说结论:可以这么说。但我不能确定它是百分百等同,因为标准没有这么说。

根据这篇文章https://mathiasbynens.be/notes/async-stack-traces Mathisas提到的,以及MDN上面的这一篇https://developer.mozilla.org/en-US/docs/Learn/JavaScript/Asynchronous/Async_await 当我们使用await的时候,JS Engine会block当前运行代码,然后启动新的Promise(task)运行,等待它的结束或者异常抛出。

这个部分我可能还要看一下emcascript的spec,确定真的理解了。但是很明显这与C#是截然不同的,差别就在于JS Engine是单线程的,而C#中会自动启动一个新的Task来做事情,当前的主Task和新启动Task是并行运行的。

在async文档中有slow async和fast async的例子,便于更深入的理解https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/async_function

那到底是用async/await还是promise?我的建议是,能用async/await的尽量用,也尽量不要和promise混用(我见过这么干的)。更细节上的判断可以参考MDN https://developer.mozilla.org/en-US/docs/Learn/JavaScript/Asynchronous/Choosing_the_right_approach

另外需要注意的一点是,如果await多个promise,那么await和Promise.all在时序上和错误处理上是有所不同的。知道了这一点,trouble shooting的时候可以更仔细的研究细节。在这里Google Chrome团队就写了一篇很实用的文章,里面提到了如何对应转换promise代码成为async/await代码 https://developers.google.com/web/fundamentals/primers/async-functions

先理解到这层面吧,如果有更深入了解再更新。