美文网首页
JS 处理异步的几种方法

JS 处理异步的几种方法

作者: 正义国王 | 来源:发表于2019-11-22 22:46 被阅读0次

    1. 异步JavaScript

    在 JS 中,经常要处理一些异步回调,比如从网络获取文件,访问数据库,从网络摄像头获得视频流;

    例如下面的代码,因为从服务器上获取一个图像需要时间,下面的代码可能不能正常工作;

    var response = fetch('myImage.png');
    var blob = response.blob();
    // display your image blob in the UI somehow
    

    那么如何解决这类问题呢?方法有很多:可分为异步callbacks(回调函数)和 其他方法(promise、async\await、generator)。下面一一介绍

    2. 异步callbacks

    以使用 XMLHttpRequest API 为例:

    function loadAsset(url, type, callback) {
      let xhr = new XMLHttpRequest();
      xhr.open('GET', url);
      xhr.responseType = type;
    
      xhr.onload = function() {
        callback(xhr.response); //把响应作为参数传递给回调函数去处理
      };
    
      xhr.send();
    }
    
    function displayImage(blob) {
      let objectURL = URL.createObjectURL(blob);
    
      let image = document.createElement('img');
      image.src = objectURL;
      document.body.appendChild(image);
    }
    
    loadAsset('coffee.jpg', 'blob', displayImage);
    

    这里我们在loadAsset函数中发出网络请求,但注意我们向loadAsset函数中传入了一个 回调函数displayImage); 当浏览器收到服务器返回来的数据时,会触发onload事件,并把响应作为参数传递给回调函数去处理。

    这样,我们就解决了之前的问题:还未收到响应数据就执行处理函数。

    3. Promise

    Promise 是专门为处理异步逻辑而设计的,它让异步回调过程更加清晰。让我们看看上面的代码使用Promise改写是怎样的:

    function loadAsset(url, type) {
      return new Promise((resolve, reject) => {
        let xhr = new XMLHttpRequest();
        xhr.open("GET", url);
        xhr.responseType = type;
    
        xhr.onload = function() {
          resolve(xhr.response); //返回收到的响应数据
        };
    
        xhr.send();
      });
    }
    
    function displayImage(blob) {
      let objectURL = URL.createObjectURL(blob);
    
      let image = document.createElement("img");
      image.src = objectURL;
      document.body.appendChild(image);
    }
    
    //不再需要传入回调函数
    loadAsset("coffee.jpg", "blob").then(data => {
      displayImage(data);
    });
    

    比较后我们会发现,这里不再需要给 loadAsset传入回调函数,Promise帮我们处理了这个逻辑,在收到响应后,由于我们使用了resolve返回响应数据,我们直接在then方法中就能拿到我们要的数据了!

    虽然代码看起来多了一点,但是逻辑看起来却更清楚了,特别是遇到 回调函数嵌套 的问题。这就是使用Promise的好处。

    4. 生成器(Generator)

    让我们看一下 Generator 的示例:

    function* say(){
        yield "开始";
        yield "执行中";
        yield "结束";
    }
    let it = say(); // 调用say方法,得到一个迭代器
    console.log(it.next()); // { value: '开始', done: false }
    console.log(it.next()); // { value: '执行中', done: false }
    console.log(it.next()); // { value: '结束', done: false }
    console.log(it.next()); // { value: undefined, done: true }
    

    生成器函数定义时在function关键字后面多加一个*号。它和普通函数不同,普通函数一次执行完所有代码,但它可以通过yield关键字将函数的执行挂起,再外部在通过调用next方法,让函数继续执行,直到遇到下一个yield,或函数执行完毕。

    这样,异步操作也可以变得和同步操作一样。

    5. async/await

    async/await 是常用的处理异步逻辑的方法,它其实就是生成器的语法糖。

    async function getData(){
      var response = await fetch('myImage.png');
      var blob = response.blob();
    }
    

    在异步处理前加 await ,这样函数将等待异步流程结束后才执行之后的代码。

    相关文章

      网友评论

          本文标题:JS 处理异步的几种方法

          本文链接:https://www.haomeiwen.com/subject/tifcwctx.html