并行(concureency)和并发(parallelism)
并发是宏观概念,任务A和任务B,在一段时间内通过任务间切换完成了两个任务,这种情况称之为为并发。
并行是微观概念,假设CPU存在两个核心,那我们可以同时完成AB两个任务。同时完成多个任务,我们称之为并并行。
为什么会有同步异步
首先JS是一个单线程的语言,单线程在执行时,所走的程序路径按照连续顺序排下来,前面的必须处理好,后面的才会执行。
为什么JS不设计成可以开多个线程同时操作呢?JS是可以操作DOM的。假设JS设计成一个多线程,主线程在给DOM的innerHTML做一个赋值操作,另一个线程把这个DOM结构删除了,那肯定是不行的。多线程可以互不干预的操作一段内存空间。
但是浏览器加载一些需要网络请求的比如图片资源、ajax。或者轮训的内容。由于单线程,需要等待这些内容访问完才可以执行下面的代码。那么我们发个ajax请求或者请求图片资源,那么在资源回来这段时间就什么也做不了,对程序是一种阻塞,在等待时间明明可以做些别的事情,此时等待是无意义的。这个时候异步就出现了,在设计要等待的操作,我们先让程序继续运行,在等待时间结束的时候,通知一下我们的程序内容执行完毕,我们可以操作这些资源了,这段时间并不影响我们程序的继续执行,只是在未来的某个时间段(不确定),有一个操作一定会执行,这就是一步。
回调函数
我们把一个函数A当作参数,传入到另外一个函数B,我们成A为回调函数。 回调函数的缺点在于易形成回调地狱。 回调函数地狱的根本原因:
- 嵌套函数存在耦合性,牵一发而动全身
- 嵌套过多,不能很好的处理错误
Gernerator
Generator最大的特点就是可以控制函数的执行
function *foo(x) {
const y = 2 * (yield(x + 1));
const z = yield( y / 3);
return x + y + z;
}
const it = foo(5);
console.log(it.next()); // {value: 6, done: true}
console.log(it.next(12)); // {value: 8, done: true}
console.log(it.next(25)); // {value: 54, done: true }
Generator和不同函数不一样,它会返回一个迭代器。我们拆解上面执行步骤
- 当执行第一次
next的时候,参数会被忽略,并且函数会停留在yield(x + 1),所以返回结果5 + 1 = 6 - 当执行第二次
next的时候,传入的参数等于第一个yield的返回值,如果不传参数,则yiled永远返回undefined。此时 y = 2 * 12,所以第二个yield返回 24 / 3 = 8; - 当执行第三个
next的时候,参数会直接给z,此时x = 5, y = 24, z = 25,所以最后结果返回5 + 24 + 25 = 54
Gernerator解决回调地狱
function *fetch() {
yiled ajax(url, () => {});
yiled ajax(url, () => {});
yiled ajax(url, () => {});
}
const it = fetch();
it.next();
it.next();
it.next();