javascript的异步编程解决方案收集

缘起

没理解js异步的同学看下面的例子:

for (var i = 0; i < 5; i++) {
  //模拟一个异步操作 setTimeout(()
=> { console.log(i); }, 1000); }

我们想要的结果是:0,1,2,3,4

结果却出乎意料:5,5,5,5,5

分析

js的特点就是单线程异步非堵塞。需要好好理解这句话:js对于异步操作,不会停下来等待上一个异步操作完成,才进行下一个异步操作。

如果要达到顺序执行,只能用回调:也就是上一个异步操作完成时,再调用下一个异步操作。

要是如上面的循环,要如何操作呢?

解决方法1

通过调用自身解决循环的回调嵌套问题

function sync(i) {
  setTimeout(() => {
    if (i < 5){
      console.log(i);
      i++;
      sync(i);
    }
  }, 1000);
}

sync(0)

解决方法2

使用await/async

优点:直观,符合同步编程思维。其实本质还是异步回调

缺点:大部分浏览器下载还不支持。需要配合Promise使用,需要写成两个函数

服务器端node.js支持。以下代码在最新版chrome浏览器中可以运行:

const f = (i) => {
  return new Promise((resolve, reject) => {
    setTimeout(() => {
      resolve(i);
    }, 1000);
  });
};

const testAsync = async () => {
  for (var i = 0; i < 5; i++) {
    const t = await f(i);
    console.log(t);
  }
};

testAsync();

解决方法3

使用co

function* useco(){
  for(var i=0; i<5; i++){
    yield new Promise((resolve, reject) => {
        setTimeout(() => {
          resolve(i);
          console.log(i);
        }, 1000);
    });
  }
}

co(useco);

依赖于上一个异步操作的结果,进行下一个异步操作:

function* useco() {
  var x=0;
  for (var i = 0; i < 5; i++) {
    x= yield new Promise((resolve, reject) => {
      setTimeout(() => {
        resolve(x+i);
      }, 1000);
    });
    console.log(x);
  }
}

co(useco).then(() => {
   console.log('执行完毕');
})
 

co还是很强大的。

解决方法4

等待补充...

原文地址:https://www.cnblogs.com/slmk/p/6684206.html