深入JavaScript

深入JavaScript Day23 - promise+gen

2022-01-25  本文已影响0人  望穿秋水小作坊

有如下需求
用【setTimeout】模拟网络请求
①传入 【why】返回【res1】
②传入 【res1 + "aaa"】返回【res2】
③传入 【res2 + "bbb"】返回【res3】
④传入 【res3 + "ccc"】返回【res4】

一、异步代码的处理方案

1、【方案一】原始调用

function requestData(params) {
  return new Promise((resolve, reject) => {
    setTimeout(() => {
      resolve(params);
    }, 2000);
  });
}

requestData("why").then((res1) => {
  console.log(res1);
  requestData(res1 + "aaa").then((res2) => {
    console.log(res2);
    requestData(res2 + "bbb").then((res3) => {
      console.log(res3);
      requestData(res3 + "ccc").then((res4) => {
        console.log(res4);
      });
    });
  });
});

2、【方案二】利用then函数返回promise,自动调用的特性,把回调放到外层,形成链式调用

requestData("why")
  .then((res1) => {
    console.log(res1);
    return requestData(res1 + "aaa");
  })
  .then((res2) => {
    console.log(res2);
    return requestData(res2 + "bbb");
  })
  .then((res3) => {
    console.log(res3);
    return requestData(res3 + "ccc");
  })
  .then((res4) => {
    console.log(res4);
  });

3、【方案三】借助Generator结合Promise,把函数调用转换成普通代码逻辑

function* createGenerator(parmas) {
  const res1 = yield requestData(parmas);
  console.log(res1);

  const res2 = yield requestData(res1 + "aaa");
  console.log(res2);

  const res3 = yield requestData(res2 + "bbb");
  console.log(res3);

  const res4 = yield requestData(res3 + "ccc");
  console.log(res4);
}

const generator = createGenerator("why");

generator.next().value.then((res1) => {
  generator.next(res1).value.then((res2) => {
    generator.next(res2).value.then((res3) => {
      generator.next(res3).value.then((res4) => {
        console.log(res4);
      });
    });
  });
});

4、【方案四】对方案三进行优化

function* createGenerator() {
  const res1 = yield requestData("why");
  console.log(res1);

  const res2 = yield requestData(res1 + "aaa");
  console.log(res2);

  const res3 = yield requestData(res2 + "bbb");
  console.log(res3);

  const res4 = yield requestData(res3 + "ccc");
  console.log(res4);
  return res4;
}

function execGenerator(genFn) {
  const generator = genFn();
  function exec(res) {
    const result = generator.next(res);
    if (result.done === true) {
      return result.value;
    } else {
      result.value.then((res1) => {
        exec(res1);
      });
    }
  }
  exec();
}

execGenerator(createGenerator);

5、【方案五】借助ES8 的 async、await 关键字

async function getData() {
  const res1 = await requestData("why");
  console.log(res1);

  const res2 = await requestData(res1 + "aaa");
  console.log(res2);

  const res3 = await requestData(res2 + "bbb");
  console.log(res3);

  const res4 = await requestData(res3 + "ccc");
  console.log(res4);
  return res4;
}

getData();

二、学习await、async

1、async是什么的缩写?

2、下面代码的执行顺序?仅仅加上async关键字的函数和普通函数执行有区别吗?

async function foo() {
  console.log("内部的代码执行-1");
}

console.log("script start-2");
foo();
console.log("script end-3");
script start-2
内部的代码执行-1
script end-3

3、观察如下代码,async关键字的函数返回值是什么?

async function foo() {
  console.log("内部的代码执行-1");
}

const result = foo();

result.then((res) => {
  console.log("返回值是Promise吗?", res);
});

console.log(result);
内部的代码执行-1
Promise {<fulfilled>: undefined}
返回值是Promise吗? undefined

4、观察如下代码,如果async函数内部抛出异常会处理?

async function foo() {
  console.log("内部的代码执行-1");
  throw new Error("async error");
  console.log("内部的代码执行-2");
}

const result = foo();

result
  .then((res) => {
    console.log("返回值是", res);
  })
  .catch((err) => {
    console.log("异常信息是", err);
  });
内部的代码执行-1
index.js:14 异常信息是 Error: async error
    at foo (index.js:3:9)
    at index.js:7:16

5、【最重要】观察如下代码,await代码执行顺序?

function requestData(params) {
  return new Promise((resolve, reject) => {
    setTimeout(() => {
      console.log(params);
      resolve(params);
    }, 2000);
  });
}

async function foo() {
  await requestData("why1");
  await requestData("why2");
  console.log("why4");
}

const result = foo();
上一篇 下一篇

猜你喜欢

热点阅读