Advanced-Frontend/Daily-Interview-Question

第 129 题:输出以下代码执行结果

Opened this issue · 13 comments

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

async function main() {
  console.time();
  const x = wait();
  const y = wait();
  const z = wait();
  await x;
  await y;
  await z;
  console.timeEnd();
}
main();

理解任务队列(消息队列)

一种是同步任务(synchronous),另一种是异步任务(asynchronous)

    // 请问最后的输出结果是什么?
    console.log("A");
    while(true){ }
    console.log("B");

如果你的回答是A,恭喜你答对了,因为这是同步任务,程序由上到下执行,遇到while()死循环,下面语句就没办法执行。

    // 请问最后的输出结果是什么?
    console.log("A");
    setTimeout(function(){
    	console.log("B");
    },0);
    while(true){}

如果你的答案是A,恭喜你现在对js运行机制已经有个粗浅的认识了!
题目中的setTimeout()就是个异步任务。在所有同步任务执行完之前,任何的异步任务是不会执行的

// new Promise(xx)相当于同步任务, 会立即执行, .then后面的是微任务
console.log('----------------- start -----------------');
setTimeout(() => {
    console.log('setTimeout');
}, 0)
new Promise((resolve, reject) =>{  // new Promise(xx)相当于同步任务, 会立即执行, .then后面的是微任务
    for (var i = 0; i < 5; i++) {
        console.log(i);
    }
    resolve();  
}).then(() => {  
    console.log('promise实例成功回调执行');
})
console.log('----------------- end -----------------');

> ----------------- start -----------------
> 0
> 1
> 2
> 3
> 4
> ----------------- end -----------------
> promise实例成功回调执行
> setTimeout

new Promise(xx)相当于同步任务, 会立即执行

所以: x,y,z 三个任务是几乎同时开始的, 最后的时间依然是10*1000ms (比这稍微大一点点, 超出部分在1x1000ms之内)

yjua commented

三个任务发起的时候没有await,可以认为是同时发起了三个异步。之后各自await任务的结果。结果按最高耗时计算,由于三个耗时一样。所以结果是 10 * 1000ms

执行wait方法是同步执行的,所以耗时是选最高的,x,y,z 的返回的结果await等于执行同步代码Promise.resolve(),await 的时候只执行同步代码

稍微改造一下就可以得到30 * 1000 ms以上的结果了
`function wait () {
return new Promise(resolve => setTimeout(resolve, 10 * 1000))
}

async function main () {
console.time()
const x = await wait()
const y = await wait()
const z = await wait()
// await x
// await y
// await z
console.timeEnd()
}

main()`

理解任务队列(消息队列)

一种是同步任务(synchronous),另一种是异步任务(asynchronous)

    请问最后的输出结果是什么?
    console.log("A");
    while(true){ }
    console.log("B");

如果你的回答是A,恭喜你答对了,因为这是同步任务,程序由上到下执行,遇到while()死循环,下面语句就没办法执行。

    请问最后的输出结果是什么?
    console.log("A");
    setTimeout(function(){
    	console.log("B");
    },0);
    while(true){}

如果你的答案是A,恭喜你现在对js运行机制已经有个粗浅的认识了!
题目中的setTimeout()就是个异步任务。在所有同步任务执行完之前,任何的异步任务是不会执行的

所以: x,y,z 三个任务是几乎同时开始的, 最后的时间依然是10*1000ms (比这稍微大一点点, 超出部分在1x1000ms之内)

这是我见过最直接明白的异步同步解释

我认为肯定是大于10s的

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

async function main() {
	console.time();
	const x = await wait(); // 每个都是都执行完才结,包括setTimeout(10*1000)的执行时间
	const y = await wait(); // 执行顺序 x->y->z 同步执行,x 与 setTimeout 属于同步执行
	const z = await wait();
	console.timeEnd(); // default: 30099.47705078125ms
	
	console.time();
	const x1 = wait(); // x1,y1,z1 同时异步执行, 包括setTimeout(10*1000)的执行时间
	const y1 = wait(); // x1 与 setTimeout 属于同步执行
	const z1 = wait();
	await x1;
	await y1;
	await z1;
	console.timeEnd(); // default: 10000.67822265625ms
	
	console.time();
	const x2 = wait(); // x2,y2,z2 同步执行,但是不包括setTimeout(10*1000)的执行时间
	const y2 = wait(); // x2 与 setTimeout 属于异步执行
	const z2 = wait();
	x2,y2,z2;
	console.timeEnd(); // default: 0.065185546875ms
}
main();
ngd-b commented

Promise 内部代码块是按序执行。和普通的代码执行顺序没区别。只是在调用then()时 返回了代码块中resolve()返回的结果,其他没有任何buf加成。
async function是为了处理Promise.resolve()以便即时获取到返回结果,await获得resolve()reject()返回的结果后会继续执行(所以resolve()reject()在哪,决定了它什么时候执行完,继续往下执行)
示例1: 将resolve() 放在同步代码块中

function wait() {
  return new Promise(resolve =>{
    console.log(1);
    resolve();
    setTimeout(function(){
      console.log(3);
      // resolve();
      console.log(4);
    }, 3* 1000);
     console.log(2);
  }
 )
}

async function main() {
  console.time();
  const x = wait();
  const y = wait();
  const z = wait();
  await x;
  await y;
  await z;
  console.timeEnd();
}
main();

image

示例2:将resolve()放到异步回调中

function wait() {
  return new Promise(resolve =>{
    console.log(1);
    // resolve();
    setTimeout(function(){
      console.log(3);
      resolve();
      console.log(4);
    }, 3* 1000);
     console.log(2);
  }
 )
}

async function main() {
  console.time();
  const x = wait();
  const y = wait();
  const z = wait();
  await x;
  await y;
  await z;
  console.timeEnd();
}
main();

image

await要得到结果才会继续执行,没有就一直等待,不会执行后面的代码。

不加await相当于x,y,z是并发执行,后面await相当于Promise.resolved(x),所以还是10*1000ms

不是并发,是同步执行

`async function test() {
console.time();
await
new Promise(resolve =>
setTimeout(resolve, 10 * 1000)
)
await
new Promise(resolve =>
setTimeout(resolve, 10 * 1000)
)
await
new Promise(resolve =>
setTimeout(resolve, 10 * 1000)
)
console.timeEnd();
}

test();`

先执行再等待,与直接执行并等待的区别吧

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

async function main() {
console.time();
const x = wait;
const y = wait;
const z = wait;
await x();
await y();
await z();
console.timeEnd();
}
main();

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

async function main() {
console.time();
const x = wait();
const y = wait();
const z = wait();
await x;
await y;
await z;
console.timeEnd();
}
main();

建议对比理解,懂了吧?

这算脑筋急转弯吗?

输出以下代码执行结果

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

async function main() {
  console.time();
  const x = wait();
  const y = wait();
  const z = wait();
  await x;
  await y;
  await z;
  console.timeEnd();
}
main();
  • new Promise是一个同步运算,会立即执行,.then里面的函数才是异步的(微任务)。所以相当于同时发起了三个异步任务,遇到await时,总时间就是三个任务中耗时最长的那个,即10*1000,所以总时间是10s多一点点

理解任务队列(消息队列)

一种是同步任务(synchronous),另一种是异步任务(asynchronous)

    // 请问最后的输出结果是什么?
    console.log("A");
    while(true){ }
    console.log("B");

如果你的回答是A,恭喜你答对了,因为这是同步任务,程序由上到下执行,遇到while()死循环,下面语句就没办法执行。

    // 请问最后的输出结果是什么?
    console.log("A");
    setTimeout(function(){
    	console.log("B");
    },0);
    while(true){}

如果你的答案是A,恭喜你现在对js运行机制已经有个粗浅的认识了!
题目中的setTimeout()就是个异步任务。在所有同步任务执行完之前,任何的异步任务是不会执行的

// new Promise(xx)相当于同步任务, 会立即执行, .then后面的是微任务
console.log('----------------- start -----------------');
setTimeout(() => {
    console.log('setTimeout');
}, 0)
new Promise((resolve, reject) =>{  // new Promise(xx)相当于同步任务, 会立即执行, .then后面的是微任务
    for (var i = 0; i < 5; i++) {
        console.log(i);
    }
    resolve();  
}).then(() => {  
    console.log('promise实例成功回调执行');
})
console.log('----------------- end -----------------');

> ----------------- start -----------------
> 0
> 1
> 2
> 3
> 4
> ----------------- end -----------------
> promise实例成功回调执行
> setTimeout

new Promise(xx)相当于同步任务, 会立即执行

所以: x,y,z 三个任务是几乎同时开始的, 最后的时间依然是10*1000ms (比这稍微大一点点, 超出部分在1x1000ms之内)

Promise.resolve()
.then(() => {
console.log("then1");
Promise.resolve()
.then(() => {
console.log("then1-1");
return Promise.resolve();
})
.then(() => {
console.log("then1-2");
});
})
.then(() => {
console.log("then2");
})
.then(() => {
console.log("then3");
})
.then(() => {
console.log("then4");
});

你好 , 能帮忙写下这个例子的执行过程吗? 尤其是微任务队列的出入情况