# 九.AsyncSeriesWaterfall

  • 只要有一个返回了不为 undefined 的值就直接结束

# 1.使用方式

let { AsyncSeriesWaterfallHook } = require("tapable")
class Lesson {
  constructor() {
    this.index = 0
    this.hooks = { arch: new AsyncSeriesWaterfallHook(["name"]) }
  }
  tap() {
    this.hooks.arch.tapAsync("node", (name, cb) => {
      setTimeout(() => {
        console.log("node", name)
        cb(null, "result")
      }, 1000)
    })
    this.hooks.arch.tapAsync("react", (name, cb) => {
      setTimeout(() => {
        console.log("react", name)
        cb("asdf")
      }, 1000)
    })
  }
  statr() {
    this.hooks.arch.callAsync("123", function() {
      console.log("end")
    })
  }
}
let l = new Lesson()
l.tap() //注册这两个事件
l.statr() //启动钩子;
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29

运行得到:

node 123
react result
end
1
2
3

# 2.原理实现

class AsyncSeriesWaterfallHook {
  //同步方法
  constructor(args) {
    //args => ['name']
    this.tasks = []
  }
  tapAsync(name, task) {
    this.tasks.push(task)
  }
  callAsync(...args) {
    let finalCallback = args.pop()
    let index = 0
    let next = (err, data) => {
      let task = this.tasks[index]
      if (!task) return finalCallback()
      if (index == 0) {
        task(...args, next)
      } else {
        task(data, next)
      }
      index++
    }
    next()
  }
}
let hook = new AsyncSeriesWaterfallHook(["name"])
let total = 0
hook.tapAsync("node", (name, cb) => {
  setTimeout(() => {
    console.log("node", name)
    cb(null, "结果")
  }, 1000)
})
hook.tapAsync("react", (data, cb) => {
  setTimeout(() => {
    console.log("react", data)
    cb(null)
  }, 1000)
})

hook.callAsync("123", function() {
  console.log("end")
})
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43