美文网首页
js异步那些事

js异步那些事

作者: 7天苹果 | 来源:发表于2017-07-24 15:35 被阅读47次

简单来说,异步编程就是在执行一个指令之后不是马上得到结果,而是继续执行后面的指令,等到特定的事件触发后,才得到结果。用 JavaScript 构建一个应用的时候经常会遇到异步编程,不管是 Node 服务端还是 Web 前端。

那如何去进行异步编程呢?就目前的标准以及草案来看,主要有下面的几种方式:

  • 回调
  • promise
  • Generator
  • await/async

一 、回调

回调函数是一段可执行的代码段,它作为一个参数传递给其他的代码,其作用是在需要的时候方便调用这段(回调函数)代码。

在JavaScript中函数也是对象的一种,同样对象可以作为参数传递给函数,因此函数也可以作为参数传递给另外一个函数,这个作为参数的函数就是回调函数。

我们在调用他的时候,不会马上得到结果,而是会继续执行后面的代码。这样,如果我们需要在查到结果之后才做某些事情的话,就需要把相关的代码写在回调里面,如果涉及到多个这样的异步操作,就势必会陷入到回调地狱中去。

回调什么时候执行

回调函数,一般在同步情境下是最后执行的,而在异步情境下有可能不执行,因为事件没有被触发或者条件不满足。

回调函数的使用场合

  • 资源加载:动态加载 js 文件后执行回调,加载 iframe 后执行回调,ajax 操作回调,图片加载完成执行回调,AJAX 等等。

  • DOM 事件及 Node.js 事件基于回调机制(Node.js 回调可能会出现多层回调嵌套的问题)。

  • setTimeout 的延迟时间为 0,这个 hack 经常被用到,settimeout 调用的函数其实就是一个 callback 的体现

  • 链式调用:链式调用的时候,在赋值器(setter) 法中(或者本身没有返回值的方法中)很容易实现链式调用,而取值器(getter)相对来说不好实现链式调用,因为你需要取值器返回你需要的数据而不是 this 指针,如果要实现链式方法,可以用回调函数来实现。

  • setTimeout、setInterval 的函数调用得到其返回值。由于两个函数都是异步的,即:他们的调用时序和程序的主流程是相对独立的,所以没有办法在主体里面等待它们的返回值,它们被打开的时候程序也不会停下来等待,否则也就失去了 setTimeout 及 setInterval 的意义了,所以用 return 已经没有意义,只能使用 callback。callback 的意义在于将 timer 执行的结果通知给代理函数进行及时处理。

例如:

var friends = ["Mike", "Stacy", "Andy", "Rick"];

friends.forEach(function (eachName, index){
console.log(index + 1 + ". " + eachName); // 1. Mike, 2. Stacy, 3. Andy, 4. Rick
});

二、Promise

Promise 是 ES 2015 原生支持的,他把原来嵌套的回调改为了级联的方式。

一般着,我们对一个 Promise 可以这样写:

var a = new Promise(function(resolve, reject) {
  setTimeout(function() {
      resolve('1')
  }, 2000)
})
a.then(function(val) {
    console.log(val)
})

如果要涉及到多个异步操作的顺序执行问题,我们可以这样写:

var a = new Promise(function(resolve, reject) {
  setTimeout(function() {
      resolve('1')
  }, 2000)
})

a
  .then(function(val){
    console.log(val)
    return new Promise(function(resolve, reject) {
      setTimeout(function() {
          resolve('2')
      }, 2000)
    })
  })
  .then(function(val) {
    console.log(val)
  })

我们只需要 return 一个 Promise 即可实现这种多个异步操作的顺序执行。

三、Generator

在 ES 2015 中,出现了 Generator 的语法。

简单来说,Generator 可以理解为一个可以遍历的状态机,调用 next 就可以切换到下一个状态。

在 JavaScript 中,Generator 的 function 与 函数名之间有一个 *, 函数内部使用 yield 关键词,定义不同的状态。

四、await/async

这是在 ES 2016 中引入的新关键词,这将在语言层面彻底解决 JavaScript 的异步回调问题,目前可以借助 babel 在生产环境中使用。使用 await/async 可以让异步的操作以同步的方式来写。

相比较来说,await/async 解决了完全使用 Promise 的一个极大痛点——不同Promise之间共享数据问题:

Promise 需要设定外层数据开始共享,这样就需要在每个then里面进行赋值,而 await/async 就不存在这样的问题,只需要以同步的方式去写就可以了。

最后借用阮一峰老师微博上的图片来比较各异步的写法:

回调,可能导致回调地狱 async/await Promise

相关文章

网友评论

      本文标题:js异步那些事

      本文链接:https://www.haomeiwen.com/subject/aljbkxtx.html