Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

第 130 题:输出以下代码执行结果,大致时间就好(不同于上题) #253

Open
yygmind opened this issue Aug 23, 2019 · 10 comments
Labels

Comments

@yygmind
Copy link
Contributor

yygmind commented Aug 23, 2019

function wait() {
  return new Promise(resolve =>
    setTimeout(resolve, 10 * 1000)
  )
}

async function main() {
  console.time();
  await wait();
  await wait();
  await wait();
  console.timeEnd();
}
main();
@ypf0088
Copy link

ypf0088 commented Aug 23, 2019

30s

@JaniceDong
Copy link

30s多点

@wind4gis
Copy link

30s多一点
调用wait函数时加上了await修饰符,导致主流程的执行必须要等待wait函数执行完才会陆续执行后续函数,相当于 await wait() => promise -> wait() -> resolve()
但是wait函数本身又写了一个promise,整个promise会setTimeout才resolve,相当于本身wait函数 => promise -> setTimeout(resolve)
那么整个串起来,流程有点类似下面这样子,promise的嵌套,只有等内部wait函数的promise -> resolve之后,才会将外部的promise -> resolve掉。然后再去执行下一个wait函数。
main -> wait -> promise -> (promise -> setTimeout(resolve))(resolve)
为啥要30s多一点,额,写入微任务队列,微任务队列里再写入任务队列,都是需要时间。

@yjua
Copy link

yjua commented Aug 23, 2019

先说结果,大概30秒多点,30秒是因为每个等待10秒,同步执行。
其实还有一个变种:

function wait() {
  return new Promise(resolve =>
    setTimeout(resolve, 10 * 1000)
  )
}

async function main() {
  console.time();
  let a = wait();
  let b = wait();
  let c = wait();
  await a;
  await b;
  await c;
  console.timeEnd();
}
main();

这个的运行时间是10s多一点,这是因为:a,b,c的异步请求会按顺序发起。而这个过程是不需要互相依赖等待的。等到wait的时候,其实是比较那个异步耗时最多。就会等待最长。最长的耗时就是整体的耗时。

如果在业务中,两个异步没有依赖关系。应该是后面这种写法。

@jjeejj
Copy link
Contributor

jjeejj commented Aug 23, 2019

这道题可以这样看执行顺序和每一步消耗的时间:

function wait() {
  return new Promise(resolve =>
    setTimeout(resolve, 10 * 1000)
  )
}

async function main() {
  console.time('ALL:');
  console.time('A:')
  await wait();
  console.timeEnd('A:');
  console.time('B:');
  await wait();
  console.timeEnd('B:');
  console.time('C:');
  await wait();
  console.timeEnd('C:');
  console.timeEnd('ALL:');
}
main();

打印的结果为:
A:: 10002.716064453125ms
B:: 10005.09814453125ms
C:: 10004.77197265625ms
ALL:: 30013.97412109375ms

@jgchenu
Copy link

jgchenu commented Aug 23, 2019

/**
 *  一切将异步貌似写为同步的写法,其实本质上都是被转换为了回调函数。
 *  首先明白一个概念,这个 async main函数返回的Promise,什么时候被resolve,就是当整段函数代码执行完返回undefined或者中途抛错。
 * await 究竟做了什么,?
 * ````
 * await foo();
 * 执行代码...
 * ```
 * 类似于Promise.resolve(foo()).then(()=>{ 执行代码... })
 **/

// 举一个简单的例子
async function foo() {
  console.log(1);
  await foo1();
  console.log(2);
}

// 等价效果
function foo() {
  return new Promise((resolve, reject) => {
    console.log(1);
    Promise.resolve(foo1()).then(() => {
      console.log(2);
    });
  });
}

// 分析题主的demo
function wait() {
  return new Promise(resolve => setTimeout(resolve, 10 * 1000));
}

async function main() {
  console.time();
  await wait();
  await wait();
  await wait();
  console.timeEnd();
}
main();

// 等价效果
function main() {
  return new Promise((resolve, reject) => {
    console.time();
    Promise.resolve(
      new Promise(resolve => setTimeout(resolve, 10 * 1000))
    ).then(() => {
      Promise.resolve(
        new Promise(resolve => setTimeout(resolve, 10 * 1000))
      ).then(() => {
        Promise.resolve(
          new Promise(resolve => setTimeout(resolve, 10 * 1000))
        ).then(() => {
          console.timeEnd();
        });
      });
    });
  });
}

/**
 * 可以看得出来,10s的定时器的回调按顺序执行,加起来就有30s了
 * 至于为什么会比30s多一些,这个要考虑,settimeOut是宏任务,Promise是微任务,
 * 在第一个事件循环,实例化promise跟执行代码都进行耗时,假设20ms之类的
 * 这个时候会执行到第一个Promise的resolve回调,执行第一个settimeout,定时器计时才开始,等10s计时完毕,才添加进去事件队列,进入下一次事件循环,pop事件跟执行回调,
 * 并且这个过程还会有v8的垃圾回收,触发新生代的From To垃圾回收跟老生代的增量标记,这部分也是需要耗时的,假设耗时80ms,所以一次settimeout下来,耗费的时间是多于10m的
 * 总的就是30s多一些
 */

@xgqfrms
Copy link

xgqfrms commented Aug 30, 2019

normal

function wait() {
  return new Promise(resolve =>
    setTimeout(resolve, 10 * 1000)
  )
}

async function main() {
  console.time();
  await wait();
  await wait();
  await wait();
  console.timeEnd();
}
main();
// Promise {<pending>}
// default: 30001.47412109375ms

better

function wait() {
  return new Promise(resolve =>
    setTimeout(resolve, 10 * 1000)
  )
}

async function main() {
  console.time();
  let a = wait();
  let b = wait();
  let c = wait();
  await a;
  await b;
  await c;
  console.timeEnd();
}
main();
// Promise {<pending>}
//  default: 10004.033203125ms

@DaYesahh
Copy link

DaYesahh commented Sep 3, 2019

30s多一点,因为js执行不会立刻执行setTimeout,而是有等待其他代码的执行。

@Jesseszhang
Copy link

/**
 *  一切将异步貌似写为同步的写法,其实本质上都是被转换为了回调函数。
 *  首先明白一个概念,这个 async main函数返回的Promise,什么时候被resolve,就是当整段函数代码执行完返回undefined或者中途抛错。
 * await 究竟做了什么,?
 * ````
 * await foo();
 * 执行代码...
 * ```
 * 类似于Promise.resolve(foo()).then(()=>{ 执行代码... })
 **/

// 举一个简单的例子
async function foo() {
  console.log(1);
  await foo1();
  console.log(2);
}

// 等价效果
function foo() {
  return new Promise((resolve, reject) => {
    console.log(1);
    Promise.resolve(foo1()).then(() => {
      console.log(2);
    });
  });
}

// 分析题主的demo
function wait() {
  return new Promise(resolve => setTimeout(resolve, 10 * 1000));
}

async function main() {
  console.time();
  await wait();
  await wait();
  await wait();
  console.timeEnd();
}
main();

// 等价效果
function main() {
  return new Promise((resolve, reject) => {
    console.time();
    Promise.resolve(
      new Promise(resolve => setTimeout(resolve, 10 * 1000))
    ).then(() => {
      Promise.resolve(
        new Promise(resolve => setTimeout(resolve, 10 * 1000))
      ).then(() => {
        Promise.resolve(
          new Promise(resolve => setTimeout(resolve, 10 * 1000))
        ).then(() => {
          console.timeEnd();
        });
      });
    });
  });
}

/**
 * 可以看得出来,10s的定时器的回调按顺序执行,加起来就有30s了
 * 至于为什么会比30s多一些,这个要考虑,settimeOut是宏任务,Promise是微任务,
 * 在第一个事件循环,实例化promise跟执行代码都进行耗时,假设20ms之类的
 * 这个时候会执行到第一个Promise的resolve回调,执行第一个settimeout,定时器计时才开始,等10s计时完毕,才添加进去事件队列,进入下一次事件循环,pop事件跟执行回调,
 * 并且这个过程还会有v8的垃圾回收,触发新生代的From To垃圾回收跟老生代的增量标记,这部分也是需要耗时的,假设耗时80ms,所以一次settimeout下来,耗费的时间是多于10m的
 * 总的就是30s多一些
 */

function wait() {
return new Promise(resolve =>
setTimeout(resolve, 10 * 1000)
)
}

async function main() {
console.time();
let a = wait();
let b = wait();
let c = wait();
await a;
await b;
await c;
console.timeEnd();
}
main();

这个怎么解释???

@libin1991
Copy link

image

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests