# 开发过程你遇到过吗?

61 阅读4分钟

开发过程你遇到过吗?

一、为什么会写这篇文章?

最近在维护公司项目的时候遇到了一个场景问题,大概代码我写成简略版如下:

let data = null //method2需要的数据
let data1 = null
function fn() {
  method1();
  method2(data);
  console.log(data1);
}

fn();

function method1() {
  // 模拟请求
  setTimeout(() => {
    data = "method1";
  }, 100);
}

function method2(currentData) {
  method3(currentData + '----' + 'method2')
}

function method3(currentData) {
  // 模拟请求
  setTimeout(() => {
    data1 = currentData;
  }, 500);
}

想必大家看到这个会觉得异常熟悉,没错就是事件循环(Event Loop)。

什么是事件循环?

由于JavaScript是单线程的,一次只能执行一个任务,可是那么多任务堆在一起时,该怎么去处理呢?

为了解决这个问题,JavaScript引擎创建了执行栈来管理任务,首先将所有的任务都放在执行栈中,通过同步方式执行栈中的任务,当遇到异步任务时,将异步任务挂起,当异步任务有了结果后,再将异步任务添加到执行栈中,等待执行。

具体细节请查看:JavaScript运行机制详解:再谈Event Loop

那么上面代码我想做到fn函数中的data1能够正常打印出method1----method2的结果,应该怎么进行修改呢?

于是就有了下面的改造方案:

let data = null //method2需要的数据
let data1 = null
async function fn() {
  await method1();
  await method2(data);
  console.log(data1);
}

fn();

function method1() {
  // 模拟请求
  new Promise((resolve, reject) => {
    setTimeout(() => {
      data = "method1";
      resolve();
    }, 100);
  });
}

function method2(currentData) {
  new Promise((resolve, reject) => {
    method3(currentData + '----' + 'method2').then(() => {
      resolve();
    });
  });
}

function method3(currentData) {
  // 模拟请求
  return new Promise((resolve, reject) => {
    setTimeout(() => {
      data1 = currentData;
      resolve();
    }, 500);
  });
}

神奇的事情发生了?

输出为:null

我不信邪在输出data1的时候给了个5s的定时器

async function fn() {
  await method1();
  await method2(data);
  settimeout(() => {
    console.log(data1);
  }, 5000);
}

神奇的事情发生了?

输出为:null----method2

这时候我陷入了思考?

  • 思考1:为什么未赋值成功,函数在遇到await的时候不是应该暂停等待执行完了,再往后执行吗?
  • 思考2:同步走到method2的时候data在method1中未被赋值成功。

二、于是带着疑惑去仔细阅读了下async/await的相关资料

发现如下:

  • 发现一:await等待一个异步执行的完成

什么意思呢?

简单来说,await后面如果是个异步函数,他会暂停后面的执行,直到异步函数执行完,并返回一个Promise.resolve()结果后,继续执行下面的代码。

肯定有人会问,Promise.reject()呢?
结果是:Promise.reject()会直接抛出错误,并终止后续的代码执行。

注意这段话:直到异步函数执行完,并返回一个Promise.resolve()结果后,继续执行下面的代码。

  • 发现二:既然await等待异步函数的执行,那把函数编程异步不就行了?

三、带着上面的发现,来重新写下代码

let data = null //method2需要的数据
let data1 = null
async function fn() {
  await method1();
  await method2(data);
    console.log(data1);
}
fn();

function method1() {
  // 模拟请求
  return new Promise((resolve, reject) => {
    setTimeout(() => {
      data = "method1";
      resolve();
    }, 100);
  });
}

function method2(currentData) {
  return new Promise((resolve, reject) => {
    method3(currentData + '----' + 'method2').then(() => {
      resolve();
    });
  });
}

function method3(currentData) {
  // 模拟请求
  return new Promise((resolve, reject) => {
    setTimeout(() => {
      data1 = currentData;
      resolve();
    }, 500);
  });
}

咦???我们发现对了。

输出结果:method1----method2

带着上面代码,我们很容易发现,原来是自己没有return出Promise.resolve()的结果导致的

四、总结

  • 在阅读别人文章时候,还是得仔细阅读,这就是平时没有仔细阅读外加没有多动手调试导致的。
  • 基础还是要多补补。
  • 仔细阅读下相关资料的源码这时候就非常有必要,比如:async/await

五、参考资料

六、今年暂定大目标

  • 阅读完经典的javascript相关书籍
  • 学习Vue3源码
  • 深入学习TypeScript,并进行实战
  • 深入学习Node.js

七、最后

第一次写文章总结,如有错误,请大佬们指出,望轻喷!!!!

你们还能有什么新的实现手段呢?可以评论区回复一起学习哦。