> js 之所以是单线程,主要为了避免资源竞争问题。
js 是单线程+无栈异步( promise )+回调异步(传统的 callback hell 就像 IndexedDB )
> 但实际上 js 不可能是单线程,就比如 xhr 图片加载,xhr 在下载时没有阻塞主线程,那图片的下载必定不是在主线程执行,那必定有一个线程帮你执行下载工作,就是网络线程。
负责下载图片等网络请求的是 chrome 的 network thread ,其跟 js 无关
> 所以我认为 js 单线程是指你在 js 代码中无法像其它语言那样使用多线程模块创建一个线程执行一个代码块。
您可以用 worker 创建新的 js thread
> 只能使用预留的 API 调用现有的线程,如浏览器的 xhr Web Api ,node 的 fs 模块
因此 xhr/fetch 本质上是浏览器暴露的一套 api ,其标准化于
https://xhr.spec.whatwg.org https://fetch.spec.whatwg.org 他们存在的目的是允许您在 js thread 中与 network thread 通信,以派发您的下载图片的任务
> 那像 xhr 中在网络线程中要渲染图片,涉及到操作 dom ,就会出现资源竞争问题,所以必须放到任务队列中让主线程来进行
xhr/fetch 没有渲染图片,他们只负责网络请求相关的 payload (实际上跟 os socket 打交道处理网络栈已经够复杂了)
xhr/fetch 最终会给您一坨 byte[]也就是您的 http request 的 http response body ,以及相关的 response 元数据如 http header ( fetch 标准是都放在
https://developer.mozilla.org/en-US/docs/Web/API/Response 里)
要么您的 js thread 去取回这些 byte[](例如通过
https://developer.mozilla.org/en-US/docs/Web/API/Response/arrayBuffer )
要么是其他浏览器 thread 消费,比如有一个`<img src="url">`,那么 network thread 下载完了`url`后就会把 byte[]传给负责图片渲染和 css layout 的 thread ,让他们绘制这个<img>,这里同样没有 js 的事(即便您禁用了浏览器 js 也不会妨碍<img src>正常工作)
要么是没有任何人消费这些 byte[],那就直接丢弃