go实现类似Promise.all的功能

主要用来加深对于goroutinechannel的理解吧

什么是Promise.all

Promise.all 可以将多个 Promise 实例包装成一个新的 Promise 实例。
同时,成功和失败的返回值是不同的,
成功的时候返回的是一个结果数组,而失败的时候则返回最先被 reject 失败状态的值

javascript

1
2
3
4
5
6
// run1和run2函数都返回promise
Promise.all([run1(), run2()]).then((res) => {
// res的数据是个数组
const [run1Res, run2Res] = res;
console.log(run1Res, run2Res);
});

go

需要用到协程 goroutine通道 channel

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
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
package main

import (
"fmt"
"sort"
"time"
)

func main() {

start := time.Now().Unix()

out1 := run1(1, 2, 0, -1, 92, 22, 33, 82, 11)
out2 := run2(1, 2, 0, -1, 92, 22, 33, 82, 11)

res1 := []int{}
res2 := []int{}

for v := range out1 {
res1 = append(res1, v)
}

for v := range out2 {
res2 = append(res2, v)
}

// 这里的耗时是4秒,而不是6秒
// 即同时执行,多协程抢占式进行任务
fmt.Println(res1, res2)
fmt.Println("耗时:", time.Now().Unix()-start, " 秒")
}

func run1(a ...int) <-chan int {
out := make(chan int)
go func() {

sort.Ints(a)

time.Sleep(time.Second * 4)

for _, v := range a {
out <- v
}

close(out)
}()
return out
}

func run2(a ...int) <-chan int {
out := make(chan int)
go func() {

sort.Ints(a)

time.Sleep(time.Second * 2)

for _, v := range a {
out <- v
}

close(out)
}()
return out
}

说明

我们可以将每个run的实现封装为promise.New的函数

上述逻辑,可以再使用promise.All的函数实现

GO 原生支持异步,用不着 promise,这完全是画蛇添足

但是这个主要是想针对多任务并行处理且同时结束的时机控制,加深对于goroutinechannel的理解吧