并发
同一时间处理多件事情的能力,滚动屏幕,动态请求内容,然后进行渲染
var count = 0,ary = [],total = 30;
for(var i = 0;i < total;i++)
{
(function(index)
{
ajax.(url,function(result)
{
ary[index] = result;
count++;
if(count == total)
{
paint();
}
})
})(i)
}
对于并发处理的多个任务,如果任务与任务之间没有联系,那么这些任务是可以并行执行的,如果任务与任务之间有依赖,那么这些任务就需要串行执行了,因此对于并发的任务处理可以总结为两种情况,一种是并行的任务处理,另一种是串行的任务处理。
并发模型
- 多线程与锁 ——JAVA
- CSP(顺序进程通信)——Erlang、Golang
- 事件循环——Javascript
为什么Javascript不选择多线程?
- 简单,不涉及共享数据与锁的处理(最大的共享数据就是DOM,试想下如果多个线程共同操作DOM的可怕后果)
- 浏览器的环境并没有很强的并行需求
事件循环
while(1)
{
var event = EventQueue.shift();
event.handler();
}
为什么要使用异步?
Javascript引擎的并发模型是单线程的事件循环模型,如果对于耗时长的操作使用同步,会使单线程的事件循环模型性能大大降低。
如何获取异步的结果?
为了能获取异步操作的结果,程序使用callback的方式,当操作完成后,往事件队列push一个事件,当事件循环处理这个事件时,发起异步操作时传入的callback就会被调用。
Callback的问题
- 代码结构不清晰
- 函数复用性差
如何优雅的处理异步
- Thunk https://github.com/thunks/thunks
- Promise https://www.promisejs.org/
- RxJS http://reactivex.io/
- generator
Thunk
<!DOCTYPE HTML>
<html lang="zh">
<head>
</head>
<body>
<script src="./thunk.js"></script>
<script>
function get(url,callback)
{
setTimeout(function()
{
callback([1,2,3])
},500)
}
var thunk = thunks();
var t = thunk(1);
thunk(function(callback)
{
//return 1
callback(null,1)
})(function(e,v)
{
console.log(e);
console.log(v);
return thunk(function(callback)
{
setTimeout(function()
{
callback(null,3)
},1000)
})
})(function(e,v)
{
console.log(e);
console.log(v)
})
/*
var getThunk = thunk.thunkify(get,'url');
getThunk(function(data)
{
console.log(data)
})
*/
</script>
</body>
</html>
Promise
<!DOCTYPE HTML>
<html lang="zh">
<head>
</head>
<body>
<script>
function get(url)
{
return new Promise(function(resolve,reject)
{
setTimeout(function()
{
resolve([1,2,3])
},500)
})
}
function handle(p)
{
return new Promise(function(resolve,reject)
{
p.then(function(data)
{
for(var i = 0,len =data.length;i < len;i++)
{
data[i]++;
}
resolve(data);
})
})
}
var p = get('url');
p = handle(p);
p.then(function(data)
{
console.log(data);
})
</script>
</body>
</html>
RxJS
<!DOCTYPE HTML>
<html lang="zh">
<head>
</head>
<body>
<button id="a" page="1"></button>
<script src="./rx.js"></script>
<script>
//Example 1
/*var comments = [
{contentid : '1',content : 'afasfsadf',uin : '1'},
{contentid : '1',content : 'afasfsadf',uin : '2'},
{contentid : '1',content : 'afasfsadf',uin : '3'},
{contentid : '1',content : 'afasfsadf',uin : '4'},
{contentid : '1',content : 'afasfsadf',uin : '4'}
]
function getComment(page,pagesize)
{
return new Promise(function(res,rej)
{
setTimeout(function()
{
res(comments)
},500)
});
}
function getNick(uin)
{
return new Promise(function(res,rej)
{
res('w');
})
}
function getLevel(uin)
{
return new Promise(function(res,rej)
{
res(10);
})
}
var clicks = Rx.Observable.fromEvent(document.getElementById('a'),'click')
.pluck('target','attributes','page','value')
.flatMap(function(data)
{
return getComment(data,10)
})
.flatMap(function(data)
{
var ary = [];
for(var i = 0;i < data.length;i++)
{
(function(index)
{
ary[index] = new Promise(function(res,rej)
{
Promise.all([getNick(data[index].uin),getLevel(data[index].uin)]).then(function(nickandlevel)
{
data[index].nick = nickandlevel[0];
data[index].level = nickandlevel[1];
res(data[index]);
})
})
})(i)
}
return Promise.all(ary);
})
clicks.subscribe(function(data)
{
console.log(data)
})*/
//Example 2
/*var ob1 = Rx.Observable.create(function(observer)
{
observer.onNext(1);
})
var ob2 = Rx.Observable.create(function(observer)
{
observer.onNext(2);
})
Rx.Observable.merge(ob1,ob2).bufferWithCount(2).subscribe(function(data)
{
console.log(data);
})*/
</script>
</body>
</html>
generator
<!DOCTYPE HTML>
<html lang="zh">
<head>
</head>
<body>
<script src="./co.js"></script>
<script>
//Example 1
/*
function sleep(t)
{
return function(callback)
{
setTimeout(function()
{
callback()
},t)
}
}
function get(url)
{
return function(callback)
{
setTimeout(function()
{
callback([1,2,3])
},500)
}
}
co(function *()
{
yield sleep(2000);
var data = yield get('url');
console.log(data);
})*/
//Example 2
/*
var script = "onmessage = function(e) { postMessage('msg from worker'); }";
function CoWorker(script)
{
return function(callback)
{
var blob = new Blob([script]);
var blobURL = window.URL.createObjectURL(blob);
var worker = new Worker(blobURL);
worker.onmessage = function(e)
{
callback(e.data);
};
worker.postMessage('');
}
}
co(function *()
{
var data = yield CoWorker(script)
console.log(data)
})*/
</script>
</body>
</html>
//co.js
function co(generator) {
var gen = generator();
function next(result) {
var step = gen.next(result);
if (!step.done) {
step.value(next);
}
}
next();
}
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。