回调函数、Promise、Generator 函数和async

发布时间 2023-06-21 14:40:06作者: carol2014

看了几篇文章,受益匪浅,写几个demo看下理解是否正确:

文章链接:Generator 函数的含义与用法 - 阮一峰的网络日志 (ruanyifeng.com)   async 函数的含义和用法 - 阮一峰的网络日志 (ruanyifeng.com)

回调函数

<script>
  //----------------------------回调函数----------------------------
  function getFile(url, myCallback) {
    let req = new XMLHttpRequest();
    req.open("GET", url);
    req.onload = function () {
      if (req.status == 200) {
        myCallback(req.responseText);
      } else {
        myCallback("Error: " + req.status);
      }
    };
    req.send();
  }
  //错误url 404
  getFile("../for-test.html", (res) => {
    console.log(res); //Error: 404
  });
  //正确url
  getFile("../../for-test.html", (res) => {
    console.log(res); //test
  });
</script>

 

多重请求导致的“回调地狱”

<script>
  //----------------------------回调函数----------------------------
  function getFile(url, myCallback) {
    let req = new XMLHttpRequest();
    req.open("GET", url);
    req.onload = function () {
      if (req.status == 200) {
        myCallback(req.responseText);
      } else {
        myCallback("Error: " + req.status);
      }
    };
    req.send();
  }
  //----------------------------多重请求时出现的多重回调函数嵌套('回调地狱')----------------------------
  getFile("../../for-test.html", (res) => {
    console.log(res); //test
    getFile("../for-test.html", (res) => {
      console.log(res); //Error: 404
    });
  });
</script>

 

Promise

<script>
  //----------------------------Promise----------------------------
  //为了解决多重请求时出现的多重回调函数嵌套('回调地狱')
  function getFilePromise(url) {
    let myPromise = new Promise((myResolve, myReject) => {
      let req = new XMLHttpRequest();
      req.open("GET", url);
      req.onload = function () {
        if (req.status == 200) {
          myResolve(req.response);
        } else {
          myReject("Error: " + req.status);
        }
      };
      req.send();
    });

    return myPromise;
  }

  getFilePromise("../../for-test.html")
    .then((value) => {
      console.log(value);
    })
    .then(() => {
      return getFilePromise("../for-test.html");
    })
    .then((value) => {
      console.log(value);
    })
    .catch(function (error) {
      console.log(error);
    });
</script>

 

Generator 函数

<script>
  //----------------------------Generator 函数----------------------------
  //"协程"(coroutine),意思是多个线程互相协作,完成异步任务。
  // 协程A开始执行,协程A执行遇到异步任务,进入暂停,执行权转移到协程B。协程B完成异步任务交还执行权给协程A。协程A恢复执行。
  // Generator 函数是协程在 ES6 的实现,最大特点就是可以交出函数的执行权(即暂停执行)。使用function* funcname 和yield定义
  function* getFileGen(url) {
    try {
      let result = yield fetch(url);
    } catch (error) {
      //捕获函数体外抛出的错误
      console.log(error);
    }
    return result;
  }
  // 调用 Generator 函数,会返回一个内部指针(即遍历器 )g,调用指针 g 的 next 方法,会移动内部指针
  // next 方法的作用是分阶段执行 Generator 函数。每次调用 next 方法,会返回一个对象,表示当前阶段的信息( value 属性和 done 属性)。
  // value 属性是 yield 语句后面表达式的值,表示当前阶段的值;done 属性是一个布尔值,表示 Generator 函数是否执行完毕,即是否还有下一个阶段。
  var g = getFileGen("../../for-test.html");
  var result = g.next();
  console.log(result); //{value: Promise, done: false}
  result.value
    .then(function (data) {
      return data.text();
    })
    .then(function (data) {
      console.log(data); //test
      console.log(g.next()); //{value: undefined, done: true}
    });

  //抛出错误
  g.throw("出错了");

  //产生的问题:流程管理(即何时执行g.next())
</script>