You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
function*numGenerator(){vari=0;console.info('Generator function start');while(i<3){console.info('Yield start');yieldi++;console.info('Yield end');}console.info('Generator function end');}varresult=numGenerator();
JS异步编程
JavaScript 运行在 JavaScript 引擎(JavaScript Engine) 中,并且是单线程的。也就是说同一时间内,只能运行一个 调用栈(Call stack),调用栈中执行一个函数,所以同一时间内只能做一件事情。
既然只有一个线程,那么 JavaScript 的并发来自于哪里呢?原因是 JavaScript 的事件驱动模型。在浏览器环境中,浏览器不只是有 runtime,还包括 webapis:如用户 DOM 操作、Ajax 请求、setTimeout。
JavaScript 的并发模型 事件驱动(Event loop)。
运行时概念:
以下是来自于 MDN 关于 JavaScript 引擎的图片:
其中:
事件循环(Event loop):
非阻塞(Non blocking):
JavaScript 处理 I/O 通常由事件或者回调函数实现。例如等待 ajax 返回时,仍然接收用户输入等。
异步模型:
JavaScript 运行时产生对象堆和调用栈,调用栈中执行函数,当调用栈中的函数执行完成时(即栈清空时),就去执行任务队列中的回调函数,而这些回调函数的产生源自于各种 WebAPI 的调用:如 DOM 事件、网络请求、定时器等。任务执行的大致流程如下图所示:
分解一下大致流程:
举例说明:
输出为:
程序解析:
JS 异步编程方法
一、回调函数:
回调函数在上文中的异步编程介绍中提到过,回调函数是指一个被作为参数传递给另一个函数(otherFunction)的函数,回调函数的调用是在 otherFunction 中,回调函数可以使命名函数,也可以是匿名函数。
下面以 Ajax 调用为例:
下面通过 Github API 查询 star 数最多的 JavaScript 项目,并通过回调函数将结果打印出来:
执行结果:
回调函数本身非常简单,也很好理解,但是由于回调函数嵌套多层使用时,会产生回调地狱(callback hell),类似于:
代码之间的高度耦合,代码变得愈发不可维护,流程控制更是变得混乱。所以有了以下更多的解决方案。
二、 Promise
Promises A+ 规范中说明,一个 Promise 是一个容器,里面是一个异步操作的最终结果。
根据规范实现的 Promise 可以将复杂的异步处理轻松地进行模式化,降低了异步处理的复杂度。
Promise 对象:
Promise 对象是一个返回值的代理,这个返回值在 Promise 对象创建时未必已知。异步方法可以像同步方法那样返回值,异步方法返回一个包含了原返回值的 Promise 对象。它允许你为异步操作的成功返回值或者失败信息指定处理方法。
Promise 状态:
Promise 对象有以下几种状态:
pending 状态的 Promise 对象可以转换成带着一个成功值的fulfilled 状态,也可变为带着一个失败信息的 rejected 状态。
Promise 状态转换:
当 Promise 对象的状态发生转换时,promise.then 绑定的方法被调用。因为Promise.prototype.then和 Promise.prototype.catch方法返回 promises对象, 所以它们可以被链式调用。
promise.then 成功和失败时都可以使用。 另外在只想对异常进行处理时可以采用 promise.then(undefined, onRejected) 这种方式,只指定reject时的回调函数即可。 不过这种情况下 promise.catch(onRejected) 应该是个更好的选择。
举例来说,使用 Promise 重写以上请求 github API 的例子:
三、ES6 Generator:
生成器函数(generator function)
生成器是一种可以从中退出并在之后重新进入的函数。生成器的环境(绑定的变量)会在每次执行后被保存,下次进入时可继续使用。
调用一个生成器函数并不马上执行它的主体,而是返回一个这个生成器函数的迭代器(iterator)对象。当这个迭代器的next()方法被调用时,生成器函数的主体会被执行直至第一个yield表达式,该表达式定义了迭代器返回的值,或者,被 yield*委派至另一个生成器函数。next()方法返回一个对象,该对象有一个value属性,表示产出的值,和一个done属性,表示生成器是否已经产出了它最后的值。
代码示例:
执行结果:
yield* 示例:
执行结果:
#### 使用 co 进行异步流程控制:
示例:
执行结果:
### 四、 async/await #### 什么是 async/await:
async 函数就是 Generator 函数的语法糖。
基本规则:
使用方式:
参考体验异步的终极解决方案
备注:
The text was updated successfully, but these errors were encountered: