js-异步解决(回调地狱)

549 阅读5分钟
  • 1、解释如何使用Thunk解决回调地狱
    • Thunk 就是利用柯里化将异步函数的回调函数参数分离出来,生成只接受一个参数(回调函数)的函数,这样保证异步任务的统一性,就可以利用数组的reduce操作统一处理,避免嵌套过多出现回调地狱
    • Thunk函数在Javascript中,目的就是将多参数函数(入参中包含了callback函数)变成单参数版本的函数。而且单参数只能是callback函数。Thunk函数实现上是针对多参数的currying(柯里化),来实现对函数的惰性求值任何函数, 只要参数有回调函数, 就能写成Thunk函数的形式。

  • 2、解释一下如何用Promise解决回调地狱
    • 1、
      • promise对象可以用来包括异步代码,一个promise实例一旦new出来了之后,它只会有三种状态,初始为pending,成功为fulfilled,失败为rejected。
      • 状态的改变有内部提供的resolve和reject方法来触发,再通过then方法去拿到resolve和reject出来的值。
      • 由于promise是链式调用的,你在then方法里面还是继续return 值出来,return出来的又是一个promise,又可以继续使用then去获取刚才return出来的值,就是利用这样的链式调用的特性,可以让我们解决回调地狱。
    • 2、
      • 通过:回调函数延迟绑定、返回值穿透、错误冒泡来解决的
      • 回调函数延迟绑定:回调函数不是直接声明的,而是通过后面的 then 方法传入的,即延迟传入
      • 返回值穿透:我们根据 then 中回调函数的传入值创建不同类型的 Promise,然后把返回的 Promise 穿透到外层,以供后续的调用。
      • 错误冒泡:在then的调用中,前面产生的错误会一直向后传递,被 catch 接收到,就不用频繁地检查错误了。

  • 3、解释一下Promise与观察者模式的关系
    • 又称作为发布-订阅模式或消息机制,定义了一种依赖关系,解决了主体对象与观察者对象之间通讯和耦合的问题\
    • Promise也使用了观察者模式的原理
      • then方法注册了成功事件
      • catch方法注册失败事件
      • resolve(value) 发布成功事件传参
      • reject(err)发布失败事件传参

  • 4、解释一下Generator是如何解决回调地狱的
    • generator允许用 function 声明一个生成器,生成器执行后返回一个迭代器(f), 生成器内可以使用 yield 关键字。
    • 每次执行 f.next() 时,函数一直执行到 yield 关键字,暂停整个函数的执行,并且返回 yield 语句的值。
    • 每次执行 f.next()都会执行到yield 关键字,直到下次碰到 yield 或者执行完毕。
    • 可以把回调数据放在yield关键字 后面,在next时候可以获取到yield的值

  • 5、Co函数的作用,如何编写Co函数?
    • co函数库是著名程序员 TJ Holowaychuk 于2013年6月发布的一个小工具,用于 Generator 函数的自动执行。
    • 使用 co 的前提条件是:Generator 函数的 yield 命令后面,只能是 Thunk 函数或 Promise 对象。
    • Generator 函数就是一个异步操作的容器。它的自动执行需要一种机制,当异步操作有了结果,能够自动交回执行权。
    • 两种方法可以做到这一点:
      • 回调函数。将异步操作包装成 Thunk 函数,在回调函数里面交回执行权。
      • Promise 对象。将异步操作包装成 Promise 对象,用 then 方法交回执行权。
function run(gen){
  var g = gen();

  function next(data){
    var result = g.next(data);
    if (result.done) return result.value;
    result.value.then(function(data){
      next(data);
    });
  }

  next();
}

run(gen); // gen 是一个 Generator 函数

只要 Generator 函数还没执行到最后一步,next 函数就递归调用,从而实现自动执行。

  • 6、解释一下Async/Await的原理
    • async 函数是什么?一句话,它就是 Generator 函数的语法糖。
    • async函数就是将 Generator 函数的星号(*)替换成async,将yield替换成await,仅此而已。
    • (1)内置执行器。
      • Generator 函数的执行必须靠执行器,所以才有了co模块,而async函数自带执行器。也就是说,async函数的执行,与普通函数一模一样,只要一行。这完全不像 Generator 函数,需要调用next方法,或者用co模块,才能真正执行,得到最后结果。
    • (2)更好的语义。
      • async和await,比起星号和yield,语义更清楚了。async表示函数里有异步操作,await表示紧跟在后面的表达式需要等待结果。
    • (3)更广的适用性。
      • co模块约定,yield命令后面只能是 Thunk 函数或 Promise 对象,而async函数的await命令后面,可以是 Promise 对象和原始类型的值(数值、字符串和布尔值,但这时会自动转成立即 resolved 的 Promise 对象)。
    • (4)返回值是 Promise。
      • async函数的返回值是 Promise 对象,这比 Generator 函数的返回值是 Iterator 对象方便多了。你可以用then方法指定下一步的操作。
    • 进一步说,async函数完全可以看作多个异步操作,包装成的一个 Promise 对象,而await命令就是内部then命令的语法糖。