thread


Javascript异步编程的4种方法

JavaScript多线程编程

HTML5多线程(Web Worker)

HTML5标准定义了一套API,允许一段javascript程序运行在主线程以外的另一个线程中。
主线程运行时,Worker子线程在后台运行,互不干扰,将结果返回给主线程。

检测浏览器是否支持Worker:
if (window.Worker) { document.write('worker thread working'); }

主线程:
let worker = new Worker('worker.js');
worker.postMessage('hello world');
worker.onmessage = function(event) {
    console.log('received message ' + event.data);
    todo();
}

worker.terminate();
worker.addEventListerner('error', function(e) {
    console.log('error', e);
});

worker线程:
addEventListerner('message', function(e) {
    postMessage('you said: ' + e.data);
}, false);

close();

使用问题:
1.同源限制
  相同的协议、域名和端口
2.访问限制
  无法使用网页的DOM对象
  window对象改写成self
  不能执行alert()和confirm()方法
  支持chrome的console和debugger断点
3.使用异步
  使用XMLHttpRequst发出AJAX请求
  使用setInterval()和setTimeout()
  使用websocker进行持续链接
  使用importScripts()加载脚本文件
  
应用场景:
1.使用专用线程进行数学运算
  处理ajax返回的大批量数据,读取用户上传文件,
  计算MD5,更改canvas的位图的过滤,分析视频和声频文件等。
2.高频用户交互
3.数据的预取

worker样例

多线程与伪线程

SetTimeOut伪线程

浏览器的内核是多线程的,一般至少实现三个常驻线程:
JavaScript引擎线程、GUI引擎线程、浏览器事件触发线程

* JavaScript引擎是基于事件驱动单线程
* GUI引擎线程浏览器界面,与JS引擎是互斥的,
  当JS引擎执行时GUI线程会被挂起,GUI更新会保存在一个队列中等JS引擎空闲时被执行
* 事件触发线程,当事件触发时该线程将事件加到处理队列的队尾,等待JS引擎来处理
  这些事件来源:
  1.来自JS引擎执行的代码如SetTimeOut
  2.浏览器内核的其他线程如鼠标点击、AJAX异步请求
  
SetTimeOut模拟一个多线程:
var thread = function () {
    var nowTime = 0, //线程已经执行了多久
        maxTime = 15;//线程最多执行多久
    var threadArr = [];//数组模拟线程队列
    
    this.addThread = function (fn) {
        threadArr.push(fn)
    }
    this.start=function () {
        doingThread();
    }
    var doingThread = function () {
        if (threadArr.length > 0) {
            if (nowTime < maxTime) {
                let now = new Date().getTime();
                var method = threadArr[0];
                method();
                threadArr.splice(0, 1);
                let nowNew = (new Date().getTime() - now);
                nowTime += nowNew;
                doingThread();
            } else {//每执行完线程后睡1ms
                nowTime=0;
                setTimeout(doingThread, 1);
            }
        }else {//先睡着等待线程队列
            setTimeout(doingThread,100)
        }
    }
}
var fn = function (num) {
    console.log(num)
}

var thread = new thread();
thread.start()
for (let i = 0; i < 1000000; i++) {
    thread.addThread(function () {
        fn(i)
    })
}

thread样例