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

第 8 题:setTimeout、Promise、Async/Await 的区别 #33

Open
baoyipin opened this issue Mar 8, 2019 · 24 comments
Open

第 8 题:setTimeout、Promise、Async/Await 的区别 #33

baoyipin opened this issue Mar 8, 2019 · 24 comments
Labels

Comments

@baoyipin
Copy link

@baoyipin baoyipin commented Mar 8, 2019

这题怎么没人答,我说下我粗浅的认识,抛砖引玉,欢迎指正和补充。
我觉得这题主要是考察这三者在事件循环中的区别,事件循环中分为宏任务队列和微任务队列。
其中settimeout的回调函数放到宏任务队列里,等到执行栈清空以后执行;
promise.then里的回调函数会放到相应宏任务的微任务队列里,等宏任务里面的同步代码执行完再执行;async函数表示函数里面可能会有异步方法,await后面跟一个表达式,async方法执行时,遇到await会立即执行表达式,然后把表达式后面的代码放到微任务队列里,让出执行栈让同步代码先执行。

@WittyBob

This comment has been minimized.

Copy link

@WittyBob WittyBob commented Mar 11, 2019

宏观任务队列
微观任务队列
的区别

@sisterAn

This comment has been minimized.

Copy link

@sisterAn sisterAn commented Mar 11, 2019

1. setTimeout

console.log('script start')	//1. 打印 script start
setTimeout(function(){
    console.log('settimeout')	// 4. 打印 settimeout
})	// 2. 调用 setTimeout 函数,并定义其完成后执行的回调函数
console.log('script end')	//3. 打印 script start
// 输出顺序:script start->script end->settimeout

2. Promise

Promise本身是同步的立即执行函数, 当在executor中执行resolve或者reject的时候, 此时是异步操作, 会先执行then/catch等,当主栈完成后,才会去调用resolve/reject中存放的方法执行,打印p的时候,是打印的返回结果,一个Promise实例。

console.log('script start')
let promise1 = new Promise(function (resolve) {
    console.log('promise1')
    resolve()
    console.log('promise1 end')
}).then(function () {
    console.log('promise2')
})
setTimeout(function(){
    console.log('settimeout')
})
console.log('script end')
// 输出顺序: script start->promise1->promise1 end->script end->promise2->settimeout

当JS主线程执行到Promise对象时,

  • promise1.then() 的回调就是一个 task

  • promise1 是 resolved或rejected: 那这个 task 就会放入当前事件循环回合的 microtask queue

  • promise1 是 pending: 这个 task 就会放入 事件循环的未来的某个(可能下一个)回合的 microtask queue 中

  • setTimeout 的回调也是个 task ,它会被放入 macrotask queue 即使是 0ms 的情况

3. async/await

async function async1(){
   console.log('async1 start');
    await async2();
    console.log('async1 end')
}
async function async2(){
    console.log('async2')
}

console.log('script start');
async1();
console.log('script end')

// 输出顺序:script start->async1 start->async2->script end->async1 end

async 函数返回一个 Promise 对象,当函数执行的时候,一旦遇到 await 就会先返回,等到触发的异步操作完成,再执行函数体内后面的语句。可以理解为,是让出了线程,跳出了 async 函数体。

举个例子:

async function func1() {
    return 1
}

console.log(func1())

在这里插入图片描述
很显然,func1的运行结果其实就是一个Promise对象。因此我们也可以使用then来处理后续逻辑。

func1().then(res => {
    console.log(res);  // 30
})

await的含义为等待,也就是 async 函数需要等待await后的函数执行完成并且有了返回结果(Promise对象)之后,才能继续执行下面的代码。await通过返回一个Promise对象来实现同步的效果。

更多可见setTimeout、Promise、Async/Await

@Fengziyin1234

This comment has been minimized.

Copy link

@Fengziyin1234 Fengziyin1234 commented Mar 29, 2019

上面的解释都很详细了。

我拿 babel es8 编译了下 async/await 结果是这样的

async function asyncTest() {
  const ret = await asyncFunction();
}

--->

function asyncGeneratorStep(gen, resolve, reject, _next, _throw, key, arg) {
  try {
    var info = gen[key](arg);
    var value = info.value;
  } catch (error) {
    reject(error);
    return;
  }
  if (info.done) {
    resolve(value);
  } else {
    Promise.resolve(value).then(_next, _throw);
  }
}

function _asyncToGenerator(fn) {
  return function() {
    var self = this,
      args = arguments;
    return new Promise(function(resolve, reject) {
      var gen = fn.apply(self, args);
      function _next(value) {
        asyncGeneratorStep(gen, resolve, reject, _next, _throw, "next", value);
      }
      function _throw(err) {
        asyncGeneratorStep(gen, resolve, reject, _next, _throw, "throw", err);
      }
      _next(undefined);
    });
  };
}

function asyncTest() {
  return _asyncTest.apply(this, arguments);
}

function _asyncTest() {
  _asyncTest = _asyncToGenerator(function*() {
    const ret = yield asyncFunction();
  });
  return _asyncTest.apply(this, arguments);
}

await/async 是通过 Generator/function* 来实现的。 所以 async/await 的相关优势也来自于generator。 Generator 是一个可以暂停 function ,感觉推出 generator 的目的包括不仅限于 Callback Hell 和 Inversion of Control。 感觉整个 community 有在往那个方向走。

function* generator(i) {
  console.log('inside before')
  yield i;
  yield i + 10;
  console.log('inside after')
}

var gen = generator(10);
console.log('outside before')
console.log(gen.next().value);
console.log(gen.next().value);
console.log('outside after')
gen.next();

结果如下

> "outside before"
> "inside before"
> 10
> 20
> "outside after"
> "inside after" // 如果不加最后一个gen.next(); 就不会有这一行
@MrRENGE

This comment has been minimized.

Copy link

@MrRENGE MrRENGE commented Apr 6, 2019

1. setTimeout

console.log('script start')	//1. 打印 script start
setTimeout(function(){
    console.log('settimeout')	// 4. 打印 settimeout
})	// 2. 调用 setTimeout 函数,并定义其完成后执行的回调函数
console.log('script end')	//3. 打印 script start
// 输出顺序:script start->script end->settimeout

2. Promise

Promise本身是同步的立即执行函数, 当在executor中执行resolve或者reject的时候, 此时是异步操作, 会先执行then/catch等,当主栈完成后,才会去调用resolve/reject中存放的方法执行,打印p的时候,是打印的返回结果,一个Promise实例。

console.log('script start')
let promise1 = new Promise(function (resolve) {
    console.log('promise1')
    resolve()
    console.log('promise1 end')
}).then(function () {
    console.log('promise2')
})
setTimeout(function(){
    console.log('settimeout')
})
console.log('script end')
// 输出顺序: script start->promise1->promise1 end->script end->promise2->settimeout

当JS主线程执行到Promise对象时,

  • promise1.then() 的回调就是一个 task
  • promise1 是 resolved或rejected: 那这个 task 就会放入当前事件循环回合的 microtask queue
  • promise1 是 pending: 这个 task 就会放入 事件循环的未来的某个(可能下一个)回合的 microtask queue 中
  • setTimeout 的回调也是个 task ,它会被放入 macrotask queue 即使是 0ms 的情况

3. async/await

async function async1(){
   console.log('async1 start');
    await async2();
    console.log('async1 end')
}
async function async2(){
    console.log('async2')
}

console.log('script start');
async1();
console.log('script end')

// 输出顺序:script start->async1 start->async2->script end->async1 end

async 函数返回一个 Promise 对象,当函数执行的时候,一旦遇到 await 就会先返回,等到触发的异步操作完成,再执行函数体内后面的语句。可以理解为,是让出了线程,跳出了 async 函数体。

举个例子:

async function func1() {
    return 1
}

console.log(func1())

在这里插入图片描述
很显然,func1的运行结果其实就是一个Promise对象。因此我们也可以使用then来处理后续逻辑。

func1().then(res => {
    console.log(res);  // 30
})

await的含义为等待,也就是 async 函数需要等待await后的函数执行完成并且有了返回结果(Promise对象)之后,才能继续执行下面的代码。await通过返回一个Promise对象来实现同步的效果。

更多可见setTimeout、Promise、Async/Await
什么叫同步的立即执行函数?建议大佬看看规范中Promise的定义。

@yygmind yygmind changed the title 第八题:setTimeout、Promise、Async/Await 的区别 第8题:setTimeout、Promise、Async/Await 的区别 Apr 26, 2019
@yygmind yygmind changed the title 第8题:setTimeout、Promise、Async/Await 的区别 第 8 题:setTimeout、Promise、Async/Await 的区别 Apr 26, 2019
@song-le-yi

This comment has been minimized.

Copy link

@song-le-yi song-le-yi commented Jul 16, 2019

有个问题,如果promise的finally方法里面出错了怎么办呀,怎么捕获呀?

@MrRENGE

This comment has been minimized.

Copy link

@MrRENGE MrRENGE commented Jul 16, 2019

有个问题,如果promise的finally方法里面出错了怎么办呀,怎么捕获呀?

会返回一个 被reject 的promise对象。继续绑定catch函数可以捕获到

@xuetupeng

This comment has been minimized.

Copy link

@xuetupeng xuetupeng commented Jul 20, 2019

async1 start

写的很好,感谢大大的分享,我还有一个疑惑上面提到的Async/Await await执行的代码 ,会跳出线程,但是await上面的打印会出现在await执行打印的前面,意思是await前面的代码都会跳出线程(异步执行),只有await后面的代码才是同步执行这个意思吗?

@rzh11111111

This comment has been minimized.

Copy link

@rzh11111111 rzh11111111 commented Jul 30, 2019

宏观微观?我记得promise的执行是在setimeout之前(好像),async/await是基于promise的

@xuetupeng

This comment has been minimized.

Copy link

@xuetupeng xuetupeng commented Jul 30, 2019

宏观微观?我记得promise的执行是在setimeout之前(好像),async/await是基于promise的

宏观吧,我其实就是比较奇怪,await前面的代码都跳出了线程吗,还是单纯就await 后面的执行跳出了线程, 也可能是我表达有问题, 为啥await以及前面代码的都会先打印 然后才是跳出线程执行外面的,最后才执行await下面的代码。

@rzh11111111

This comment has been minimized.

Copy link

@rzh11111111 rzh11111111 commented Jul 30, 2019

宏观微观?我记得承诺的执行是在setimeout之前(好像),异步/ AWAIT是基于承诺的

宏观吧,我其实就是比较奇怪,等待前面的代码都跳出了线程吗,还是单纯就等待后面的执行跳出了线程,也可能是我表达有问题,为啥等待以及前面代码的都会先打印然后才是跳出线程执行外面的,最后才执行的await下面的代码。

就像setimeout是1,2,3这样的顺序来的,但是promise是1.1,1.2,promise是微观的,async,await基于promise也大概和promise一样

@xuetupeng

This comment has been minimized.

Copy link

@xuetupeng xuetupeng commented Jul 30, 2019

宏观微观?我记得承诺的执行是在setimeout之前(好像),异步/ AWAIT是基于承诺的

宏观吧,我其实就是比较奇怪,等待前面的代码都跳出了线程吗,还是单纯就等待后面的执行跳出了线程,也可能是我表达有问题,为啥等待以及前面代码的都会先打印然后才是跳出线程执行外面的,最后才执行的await下面的代码。

就像setimeout是1,2,3这样的顺序来的,但是promise是1.1,1.2,promise是微观的,async,await基于promise也大概和promise一样
恩,这个其实是了解的,就是Async/Await的有点没吃透,Await前面的语句 和Await后面的语句,两者间的差异, 就是为啥不是await 的内容 先输出 然后await上面和下面再输出

@rzh11111111

This comment has been minimized.

Copy link

@rzh11111111 rzh11111111 commented Jul 30, 2019

宏观微观?我记得承诺的执行是在setimeout之前(好像),异步/ AWAIT是基于承诺的

宏观吧,我其实就是比较奇怪,等待前面的代码都跳出了线程吗,还是单纯就等待后面的执行跳出了线程,也可能是我表达有问题,为啥等待以及前面代码的都会先打印然后才是跳出线程执行外面的,最后才执行的await下面的代码。

就像setimeout是1,2,3这样的顺序来的,但是promise是1.1,1.2,promise是微观的,async,await基于promise也大概和promise一样
恩,这个其实是了解的,就是Async/Await的有点没吃透,Await前面的语句 和Await后面的语句,两者间的差异, 就是为啥不是await 的内容 先输出 然后await上面和下面再输出

async/await不是同步了嘛,我也缕的不是很清楚,第10题那个回答挺好的

@FoooooooF

This comment has been minimized.

Copy link

@FoooooooF FoooooooF commented Aug 2, 2019

2. 基础知识

需要先看懂这两份资料,他们会让你构建一个完整的从 上下文执行栈,Event Loop,任务队列(task queue),再到Microtask(微任务)、Macrotask/Task(宏任务)知识体系。看完这个来解决一些setTimeout,pormsie,async 的执行先后问题,简直都是毛毛雨!

js运行原理

首先补齐基础,来看一下js 引擎(如:V8)的运行原理,这位Philip Roberts小哥讲的非常好,运行过程都使用动画展现,过程非常生动,条理也很清楚,当然ppt也做的不错。
这是B站上带英文字幕的版本
视频地址

这个是核心思想的截图
evnet loop

Microtask、Macrotask/Task

Philip Roberts视频中缺少了任务队列(task queue)区分为Microtask(微任务)、Macrotask/Task(宏任务)的部分,这里需要看第二份资料,详细的介绍了Microtask、Macrotask/Task 的运行过程,且分析了浏览器的执行差异,Jake Archibald英文博客地址

看博客注意事项

  • 博客内有带执行步骤的动画,一定要亲自点一下⭐️

  • 博客中将Macrotask叫做Task;

  • 分析浏览器差异的部分基本可以略过了,随着版本更新,这些差异基本都被修补了。我们只要看博客中关于chrome浏览器的正确输出结果就可以了

Microtask和Macrotask所包含的api:

Microtask
- process.nextTick
- promise
- Object.observe (废弃)
- MutationObserver

Macrotask
- setTimeout
- setImmediate
- setInterval
- I/O
- UI 渲染

如果不想看英文博客,我在这里作一点简单的总结:

  1. 在执行上下文栈的同步任务执行完后;
  2. 首先执行Microtask队列,按照队列先进先出的原则,一次执行完所有Microtask队列任务;
  3. 然后执行Macrotask/Task队列,一次执行一个,一个执行完后,检测 Microtask是否为空;
  4. 为空则执行下一个Macrotask/Task;
  5. 不为空则执行Microtask

更多内容可以看我的github

@xuanbabybaby

This comment has been minimized.

Copy link

@xuanbabybaby xuanbabybaby commented Aug 9, 2019

宏观微观?我记得承诺的执行是在setimeout之前(好像),异步/ AWAIT是基于承诺的

宏观吧,我其实就是比较奇怪,等待前面的代码都跳出了线程吗,还是单纯就等待后面的执行跳出了线程,也可能是我表达有问题,为啥等待以及前面代码的都会先打印然后才是跳出线程执行外面的,最后才执行的await下面的代码。

就像setimeout是1,2,3这样的顺序来的,但是promise是1.1,1.2,promise是微观的,async,await基于promise也大概和promise一样
恩,这个其实是了解的,就是Async/Await的有点没吃透,Await前面的语句 和Await后面的语句,两者间的差异, 就是为啥不是await 的内容 先输出 然后await上面和下面再输出

几乎同样的疑问,,,我搞不懂为什么await下面的代码会在script end之后输出,,我以为是在async2执行完就会执行的 然后才执行 script end,,,,不太懂

@rosefang

This comment has been minimized.

Copy link

@rosefang rosefang commented Aug 24, 2019

2. 基础知识

需要先看懂这两份资料,他们会让你构建一个完整的从 上下文执行栈,Event Loop,任务队列(task queue),再到Microtask(微任务)、Macrotask/Task(宏任务)知识体系。看完这个来解决一些setTimeout,pormsie,async 的执行先后问题,简直都是毛毛雨!

js运行原理

首先补齐基础,来看一下js 引擎(如:V8)的运行原理,这位Philip Roberts小哥讲的非常好,运行过程都使用动画展现,过程非常生动,条理也很清楚,当然ppt也做的不错。
这是B站上带英文字幕的版本
视频地址

这个是核心思想的截图
evnet loop

Microtask、Macrotask/Task

Philip Roberts视频中缺少了任务队列(task queue)区分为Microtask(微任务)、Macrotask/Task(宏任务)的部分,这里需要看第二份资料,详细的介绍了Microtask、Macrotask/Task 的运行过程,且分析了浏览器的执行差异,Jake Archibald英文博客地址

看博客注意事项

  • 博客内有带执行步骤的动画,一定要亲自点一下star
  • 博客中将Macrotask叫做Task;
  • 分析浏览器差异的部分基本可以略过了,随着版本更新,这些差异基本都被修补了。我们只要看博客中关于chrome浏览器的正确输出结果就可以了

Microtask和Macrotask所包含的api:

Microtask
- process.nextTick
- promise
- Object.observe (废弃)
- MutationObserver

Macrotask
- setTimeout
- setImmediate
- setInterval
- I/O
- UI 渲染

如果不想看英文博客,我在这里作一点简单的总结:

  1. 在执行上下文栈的同步任务执行完后;
  2. 首先执行Microtask队列,按照队列先进先出的原则,一次执行完所有Microtask队列任务;
  3. 然后执行Macrotask/Task队列,一次执行一个,一个执行完后,检测 Microtask是否为空;
  4. 为空则执行下一个Macrotask/Task;
  5. 不为空则执行Microtask

更多内容可以看我的github

image
你好,这里的例子是写错了吧,实际运行不是这样的结果呢

@FoooooooF

This comment has been minimized.

Copy link

@FoooooooF FoooooooF commented Aug 27, 2019

文章中的例子确实写错了

2. 基础知识

需要先看懂这两份资料,他们会让你构建一个完整的从 上下文执行栈,Event Loop,任务队列(task queue),再到Microtask(微任务)、Macrotask/Task(宏任务)知识体系。看完这个来解决一些setTimeout,pormsie,async 的执行先后问题,简直都是毛毛雨!

js运行原理

首先补齐基础,来看一下js 引擎(如:V8)的运行原理,这位Philip Roberts小哥讲的非常好,运行过程都使用动画展现,过程非常生动,条理也很清楚,当然ppt也做的不错。
这是B站上带英文字幕的版本
视频地址
这个是核心思想的截图
evnet loop

Microtask、Macrotask/Task

Philip Roberts视频中缺少了任务队列(task queue)区分为Microtask(微任务)、Macrotask/Task(宏任务)的部分,这里需要看第二份资料,详细的介绍了Microtask、Macrotask/Task 的运行过程,且分析了浏览器的执行差异,Jake Archibald英文博客地址
看博客注意事项

  • 博客内有带执行步骤的动画,一定要亲自点一下star
  • 博客中将Macrotask叫做Task;
  • 分析浏览器差异的部分基本可以略过了,随着版本更新,这些差异基本都被修补了。我们只要看博客中关于chrome浏览器的正确输出结果就可以了

Microtask和Macrotask所包含的api:

Microtask
- process.nextTick
- promise
- Object.observe (废弃)
- MutationObserver

Macrotask
- setTimeout
- setImmediate
- setInterval
- I/O
- UI 渲染

如果不想看英文博客,我在这里作一点简单的总结:

  1. 在执行上下文栈的同步任务执行完后;
  2. 首先执行Microtask队列,按照队列先进先出的原则,一次执行完所有Microtask队列任务;
  3. 然后执行Macrotask/Task队列,一次执行一个,一个执行完后,检测 Microtask是否为空;
  4. 为空则执行下一个Macrotask/Task;
  5. 不为空则执行Microtask

更多内容可以看我的github

image
你好,这里的例子是写错了吧,实际运行不是这样的结果呢

文章中的的结果确实写错了,现在已经更正.谢谢你的指正! 如果对你造成误导,非常抱歉!

@qylbj2016

This comment has been minimized.

Copy link

@qylbj2016 qylbj2016 commented Aug 31, 2019

这题怎么没人答,我说下我粗浅的认识,抛砖引玉,欢迎指正和补充。
我觉得这题主要是考察这三者在事件循环中的区别,事件循环中分为宏任务队列和微任务队列。
其中settimeout的回调函数放到宏任务队列里,等到执行栈清空以后执行;
promise.then里的回调函数会放到相应宏任务的微任务队列里,等宏任务里面的同步代码执行完再执行;async函数表示函数里面可能会有异步方法,await后面跟一个表达式,async方法执行时,遇到await会立即执行表达式,然后把表达式后面的代码放到微任务队列里,让出执行栈让同步代码先执行。

第一次执行栈的同步任务都完成后,接着处理的应该是微任务吧,然后再从宏任务队列里拿一条宏任务到执行栈中,等执行栈中的宏任务处理完,再去清空微任务队列。

@gaozf

This comment has been minimized.

Copy link

@gaozf gaozf commented Sep 1, 2019

               async function async1() {
			await async2();
			console.log('async1 end');
		}

		async function async2() {
			return 'async2';
			// return Promise.resolve('async2');
		}

		async1();

		new Promise(function(resolve) {
			resolve();
		}).then(function() {
			console.log('Promise then');
		});

async函数本身返回是一个promise,为什么async2显式返回promise和不显式返回,两行打印顺序不一致,什么原理?显式返回顺序:Promise then --> async1 end;返回普通值顺序:async1 end --> Promise then

@weixiaoxu123

This comment has been minimized.

Copy link

@weixiaoxu123 weixiaoxu123 commented Sep 7, 2019

setTimeout 和promise 好理解, 宏任务队列和微任务队列。,
await fun() \n balabala..
await返回一个promise 后执行 balabala 所以我的理解就像使用了.then(()=>balabala),也是进入的微任务队列。 这样执行的顺序也就明白了

@bibi7 bibi7 mentioned this issue Oct 10, 2019
@NARUTOne

This comment has been minimized.

Copy link

@NARUTOne NARUTOne commented Nov 14, 2019

Event Loop

@zytxh

This comment has been minimized.

Copy link

@zytxh zytxh commented Nov 21, 2019

有个问题,如果promise的finally方法里面出错了怎么办呀,怎么捕获呀?

finally也是返回一个promise,自然可以用catch捕获运行时错误。

@yinzuowen

This comment has been minimized.

Copy link

@yinzuowen yinzuowen commented Nov 27, 2019

               async function async1() {
			await async2();
			console.log('async1 end');
		}

		async function async2() {
			return 'async2';
			// return Promise.resolve('async2');
		}

		async1();

		new Promise(function(resolve) {
			resolve();
		}).then(function() {
			console.log('Promise then');
		});

async函数本身返回是一个promise,为什么async2显式返回promise和不显式返回,两行打印顺序不一致,什么原理?显式返回顺序:Promise then --> async1 end;返回普通值顺序:async1 end --> Promise then

return ‘async2’时,执行代码相当于如下:
new Promise(function (resolve) {
resolve('async2');
}).then(function() {
console.log('async1 end');
});
console.log('async1 end');排在microtask queue前面,所以输出顺序是async1 end --> Promise then

return Promise.resolve('async2')时,执行代码相当于如下:
new Promise(function (resolve) {
resolve(Promise.resolve('async2'));
}).then(function() {
console.log('async1 end');
});
此时的then取决于里层promise的状态,console.log('async1 end')会排在microtask queue后面,所以输出顺序是Promise then --> async1 end

@yygmind yygmind added the 异步 label Dec 16, 2019
@SnailOwO

This comment has been minimized.

Copy link

@SnailOwO SnailOwO commented Dec 27, 2019

自己回答一波,若有错误请各位指出,互相学习!谢谢 ~
鉴于上面各位大佬回答的,其实这题主要还是考浏览器的EVENT LOOP
setTimeout属于宏任务,Promise属于微任务.而async和await其实是geneorator的语法糖,实质上最后返回的也是promise,所以我将其归为微任务(有错的,请指出,谢谢)。

而浏览器的执行顺序是在一开始会通篇扫描整个脚本,生成主执行栈,用于执行同步任务.而异步任务会加入至浏览器的任务队列中.当执行栈为空,就会去Task队列中(任务队列)取出需要执行的代码放入执行栈中去执行。而Task队列中,我们又再之前提及到分:微任务和宏任务

微任务的优先级大于宏任务,所以在执行栈为空的时候,首先会去执行Micortask(微任务)队列,执行完毕后再去取Macrotask(宏任务)队列去执行栈中执行,一次执行一个,再去检查Micortask(微任务),若存在则执行Microtask,若没有则取下一个Macrotask任务继续执行,直至为空。
以上,是我对EventLoop的回答,但是我还是想在此基础上回答下关于这三个的异步不同之处。
--------------------分隔线-------------------------------
setTimeout的异步使用方法算是比较古老的回调函数方式,就是我们之前写Jquery的时候,ajax的最常见的使用方式,这种的好处在于用很简单的方式实现了异步的方式,从而解决了异步直肠子的问题(耗时任务,一直处于等待)。缺点:回调地狱,这是写了多年Jq的一直很恶心的地方,代码嵌套太多,牵一发而动全身。

至此,从而发展出了Promise!!!
优点:解决了回调函数的问题,可以使用链式结构,代码逻辑清晰。
缺点:无法取消,有时逻辑复杂then太多,then中嵌套then,错误捕获不到正确的位置,只能通过自己的catch或者写reject(erro)的回调来捕获。

至此,我们再次引出我们的Async/Await语法糖
优点:以同步代码的方式去写异步,代码逻辑清晰,符合我们平时写的逻辑。缺点:因为await将异步代码改造成了同步代码,如果多个异步代码没有依赖性却使用了await会导致性能上的降低。(这个是可以避免的)

@JiangMengLei

This comment has been minimized.

Copy link

@JiangMengLei JiangMengLei commented Jan 11, 2020

宏观微观?我记得承诺的执行是在setimeout之前(好像),异步/ AWAIT是基于承诺的

宏观吧,我其实就是比较奇怪,等待前面的代码都跳出了线程吗,还是单纯就等待后面的执行跳出了线程,也可能是我表达有问题,为啥等待以及前面代码的都会先打印然后才是跳出线程执行外面的,最后才执行的await下面的代码。

就像setimeout是1,2,3这样的顺序来的,但是promise是1.1,1.2,promise是微观的,async,await基于promise也大概和promise一样
恩,这个其实是了解的,就是Async/Await的有点没吃透,Await前面的语句 和Await后面的语句,两者间的差异, 就是为啥不是await 的内容 先输出 然后await上面和下面再输出

async/await不是同步了嘛,我也缕的不是很清楚,第10题那个回答挺好的

引用阮一峰老师书中一句话:“ async 函数返回一个 Promise 对象,当函数执行的时候,一旦遇到 await 就会先返回,等到触发的异步操作完成,再接着执行函数体内后面的语句。”
简单的说,先去执行后面的同步任务代码,执行完成后,也就是表达式中的 Promise 解析完成后继续执行 async 函数并返回解决结果。(其实还是本轮循环promise的问题,最后的resolve属于异步,位于本轮循环的末尾。)

async1 end --> Promise then

我试了 结果一样啊  都是 async1 end --> Promise then
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
You can’t perform that action at this time.