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

看了几篇文章,受益匪浅,写几个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>

 async函数

<script>
  //----------------------------async 函数----------------------------
  //async函数,也就是我们常说的async/await,是在ES2017(ES8)引入的新特性,主要目的是为了简化使用基于Promise的API时所需的语法。
  //async 表示函数里有异步操作,await 表示紧跟在后面的表达式需要等待结果。await关键字只在async函数内有效,如果在async函数体之外使用它,会抛出语法错误。
  // async 函数返回一个 Promise 对象,可以使用 then 方法添加回调函数。
  async function test() {
    return "hello";
  }
  test()
    .then((res) => {
      console.log(res);
    })
    .catch((error) => {
      console.log(error);
    });

  async function test1() {
    return new Promise(function (resolve, reject) {
      if (true) {
        resolve("hello");
      } else {
        reject("error");
      }
    });
  }
  test1()
    .then((res) => {
      console.log(res);
    })
    .catch((error) => {
      console.log(error);
    });

  //await关键字可以跟在任意变量或者表达式之前,但通常await后面会跟一个异步过程。await使用时,会阻塞后续代码执行。
  async function test2() {
    var result = await fetch("../../for-test.html")
      .then((response) => response.text())
      .catch((err) => console.log("Request Failed", err));
    var result1 = await "test2";
    console.log(result);
    console.log(result1);
  }
  test2();
</script>

 

posted @ 2023-06-21 14:38  carol2014  阅读(6)  评论(0编辑  收藏  举报