English | 中文
Introducing VowLink
in a few words can be challenging. Even though I have finished the first version of VowLink
, I still struggle to find the perfect way to describe it.
In my development experience, I have often encountered the problem of code being too nested and logic becoming too complex. I wanted to find a solution that would allow me to avoid getting stuck in the middle of the code and simplify the logic. That's when I discovered the promise concept in ES6, which was a step in the right direction but not perfect. This inspired me to create something better.
And thus, VowLink
was born. It is a Golang project that draws inspiration from ES6 promises and provides a powerful tool for chaining function calls.
- Simple and easy to use
- No third-party dependencies
- Supports various methods such as
then()
,catch()
,finally()
,all()
,race()
,any()
,allSettled()
go get github.com/shengyanli1982/vowlink
With VowLink
, you can start using it in just a few minutes. It's incredibly easy to use and requires minimal setup.
Example
package main
import (
"fmt"
vl "github.com/shengyanli1982/vowlink"
)
func main() {
// vowlink 像一个链条,你可以在链条上添加更多的 then() 来在 promise 解析后做更多的事情。
// vowlink is like a chain, you can add more then() to the chain to do more things after the promise is resolved.
result := vl.NewPromise(func(resolve func(interface{}, error), reject func(interface{}, error)) {
// 这个 promise 直接解析为 "hello world"
// This promise is directly resolved to "hello world"
resolve("hello world", nil)
}).Then(func(value interface{}) (interface{}, error) {
// 在第一个 Then 方法中,我们将解析的值加上 " vowlink"
// In the first Then method, we append " vowlink" to the resolved value
return value.(string) + " vowlink", nil
}, nil).Then(func(value interface{}) (interface{}, error) {
// 在第二个 Then 方法中,我们将解析的值加上 " !!"
// In the second Then method, we append " !!" to the resolved value
return value.(string) + " !!", nil
}, nil)
// 从 promise 中获取值并打印
// Get the value from the promise and print it
fmt.Println(result.GetValue())
}
Result
$ go run demo.go
hello world vowlink !!
It's so easy, right?
Instead of using the same old examples to explain how to use VowLink, let's dive into a real case to demonstrate its usage. By using practical examples, we can better understand how VowLink can help us achieve our goals.
Important
The Rules
section is the core of the VowLink
project. It is important to understand the rules before using VowLink
.
- All
Then
,Catch
, andFinally
methods of a Promise can return an error. If an error is returned (even if it is the original error), it will be handled by the nextThen
orCatch
method until the returned error is nil. vowlink
supports theresolve
andreject
methods, which can return data and error, allowingNewPromise
to make a second choice.- The
GetValue
andGetReason
methods are specific to the Promise and are terminal methods, meaning they do not return aPromise
object. - Although
vowlink
is inspired byJavaScript Promise
, it is not identical toJavaScript Promise
asGolang
has its own differences.
There are various cases in our work, and I will show you some examples. You can find the code for each case in the examples
directory. For example, Case 1 is located in examples/case1
.
Just like using if
and else
in our code, we often want to perform certain actions if a condition is true, and different actions if the condition is false.
Example
package main
import (
"fmt"
vl "github.com/shengyanli1982/vowlink"
)
func main() {
// vowlink 像一个链条,你可以在链条上添加更多的 then() 来在 promise 解析后做更多的事情。
// vowlink is like a chain, you can add more then() to the chain to do more things after the promise is resolved.
result := vl.NewPromise(func(resolve func(interface{}, error), reject func(interface{}, error)) {
// 这个 promise 直接解析为 "hello world"
// This promise is directly resolved to "hello world"
resolve("hello world", nil)
}).Then(func(value interface{}) (interface{}, error) {
// 在 Then 方法中,我们将解析的值加上 " vowlink !!"
// In the Then method, we append " vowlink !!" to the resolved value
return value.(string) + " vowlink !!", nil
}, func(err error) (interface{}, error) {
// 如果 promise 被拒绝,我们将返回一个新的错误信息 "rejected."
// If the promise is rejected, we return a new error message "rejected."
return nil, fmt.Errorf("rejected.")
})
// 从 promise 中获取值并打印
// Get the value from the promise and print it
fmt.Println("Resolve:", result.GetValue())
// 这是一个被拒绝的 promise
// This is a rejected promise
result = vl.NewPromise(func(resolve func(interface{}, error), reject func(interface{}, error)) {
// 这个 promise 被拒绝,原因是 "error"
// This promise is rejected with the reason "error"
reject(nil, fmt.Errorf("error"))
}).Then(func(value interface{}) (interface{}, error) {
// 如果 promise 被解析,我们将解析的值加上 " vowlink"
// If the promise is resolved, we append " vowlink" to the resolved value
return value.(string) + " vowlink", nil
}, func(err error) (interface{}, error) {
// 如果 promise 被拒绝,我们将返回一个新的错误信息 "rejected."
// If the promise is rejected, we return a new error message "rejected."
return nil, fmt.Errorf("rejected.")
})
// 从 promise 中获取拒绝的原因并打印
// Get the reason for the rejection from the promise and print it
fmt.Println("Rejected:", result.GetReason().Error())
}
Result
$ go run demo.go
Resolve: hello world vowlink !!
Rejected: rejected.
I prefer using JavaScript-style code in Golang. I want to use then()
to perform actions after the promise is resolved and catch()
to handle rejected promises.
Example
package main
import (
"fmt"
vl "github.com/shengyanli1982/vowlink"
)
func main() {
// vowlink 像一个链条,你可以在链条上添加更多的 then() 来在 promise 解析后做更多的事情。
// vowlink is like a chain, you can add more then() to the chain to do more things after the promise is resolved.
result := vl.NewPromise(func(resolve func(interface{}, error), reject func(interface{}, error)) {
// 这个 promise 直接解析为 "hello world"
// This promise is directly resolved to "hello world"
resolve("hello world", nil)
}).Then(func(value interface{}) (interface{}, error) {
// 在 Then 方法中,我们将解析的值加上 " vowlink !!"
// In the Then method, we append " vowlink !!" to the resolved value
return value.(string) + " vowlink !!", nil
}, nil).Catch(func(err error) (interface{}, error) {
// 如果 promise 被拒绝,我们将返回一个新的错误信息 "rejected."
// If the promise is rejected, we return a new error message "rejected."
return nil, fmt.Errorf("rejected.")
})
// 从 promise 中获取值并打印
// Get the value from the promise and print it
fmt.Println("Resolve:", result.GetValue())
// 这是一个被拒绝的 promise
// This is a rejected promise
result = vl.NewPromise(func(resolve func(interface{}, error), reject func(interface{}, error)) {
// 这个 promise 被拒绝,原因是 "error"
// This promise is rejected with the reason "error"
reject(nil, fmt.Errorf("error"))
}).Then(func(value interface{}) (interface{}, error) {
// 如果 promise 被解析,我们将解析的值加上 " vowlink !!"
// If the promise is resolved, we append " vowlink !!" to the resolved value
return value.(string) + " vowlink !!", nil
}, nil).Catch(func(err error) (interface{}, error) {
// 如果 promise 被拒绝,我们将返回一个新的错误信息 "rejected."
// If the promise is rejected, we return a new error message "rejected."
return nil, fmt.Errorf("rejected.")
})
// 从 promise 中获取拒绝的原因并打印
// Get the reason for the rejection from the promise and print it
fmt.Println("Rejected:", result.GetReason().Error())
}
Result
$ go run demo.go
Resolve: hello world vowlink !!
Rejected: rejected.
I want to use finally()
to do something after the promise is resolved or rejected.
Example
package main
import (
"errors"
"fmt"
vl "github.com/shengyanli1982/vowlink"
)
func main() {
// 输出 "========== finally 1 successfully ==========" 到控制台
// Print "========== finally 1 successfully ==========" to the console
fmt.Println("========== finally 1 successfully ==========")
// vowlink 像一个链条,你可以在链条上添加更多的 then() 来在 promise 解析后做更多的事情。
// vowlink is like a chain, you can add more then() to the chain to do more things after the promise is resolved.
result := vl.NewPromise(func(resolve func(interface{}, error), reject func(interface{}, error)) {
// 这个 promise 直接解析为 "hello world"
// This promise is directly resolved to "hello world"
resolve("hello world", nil)
}).Then(func(value interface{}) (interface{}, error) {
// 在 Then 方法中,我们将解析的值加上 " vowlink !!"
// In the Then method, we append " vowlink !!" to the resolved value
return value.(string) + " vowlink !!", nil
}, nil).Catch(func(err error) (interface{}, error) {
// 如果 promise 被拒绝,我们将返回一个新的错误信息 "rejected."
// If the promise is rejected, we return a new error message "rejected."
return nil, fmt.Errorf("rejected.")
}).Finally(func() error {
// 不论 promise 是被解析还是被拒绝,Finally 方法都会被调用,并打印 "finally 1"
// Whether the promise is resolved or rejected, the Finally method will be called and print "finally 1"
fmt.Println("finally 1")
// 返回 nil 表示 Finally 方法执行成功
// Return nil indicates that the Finally method was executed successfully
return nil
})
// 使用 Printf 函数输出 "finally 1 is called. value: %v, error: %v\n" 到控制台
// 使用 result.GetValue() 和 result.GetReason() 作为 Printf 函数的参数
// Use the Printf function to output "finally 1 is called. value: %v, error: %v\n" to the console
// Use result.GetValue() and result.GetReason() as the parameters of the Printf function
fmt.Printf("finally 1 is called. value: %v, error: %v\n", result.GetValue(), result.GetReason())
// 输出 "========== finally 1 error ==========" 到控制台
// Print "========== finally 1 error ==========" to the console
fmt.Println("========== finally 1 error ==========")
result = vl.NewPromise(func(resolve func(interface{}, error), reject func(interface{}, error)) {
// 这个 promise 直接解析为 "hello world"
// This promise is directly resolved to "hello world"
resolve("hello world", nil)
}).Then(func(value interface{}) (interface{}, error) {
// 在 Then 方法中,我们将解析的值加上 " vowlink !!"
// In the Then method, we append " vowlink !!" to the resolved value
return value.(string) + " vowlink !!", nil
}, nil).Catch(func(err error) (interface{}, error) {
// 如果 promise 被拒绝,我们将返回一个新的错误信息 "rejected."
// If the promise is rejected, we return a new error message "rejected."
return nil, fmt.Errorf("rejected.")
}).Finally(func() error {
// Finally 函数会在 Promise 完成(无论解决还是拒绝)后被调用
// The Finally function will be called after the Promise is settled (either resolved or rejected)
fmt.Println("finally error: 1")
// 返回一个新的错误 "error in finally 1"
// Return a new error "error in finally 1"
return errors.New("error in finally 1")
}).Then(func(data interface{}) (interface{}, error) {
// 当 Promise 被解决时,会执行这个 Then 函数
// This Then function will be executed when the Promise is resolved
// 返回解决的值,将会被下一个 Then 函数接收
// Return the resolved value, which will be received by the next Then function
return data.(string) + " vowlink", nil
}, func(reason error) (interface{}, error) {
// 当 Promise 被拒绝时,会执行这个 Catch 函数
// This Catch function will be executed when the Promise is rejected
// 返回一个新的错误 "Handled error: " 加上原因的错误信息
// Return a new error "Handled error: " plus the error message of the reason
return nil, errors.New("Handled error: " + reason.Error())
})
// 使用 Printf 函数输出 "finally 1 error, but then is called. value: %v, error: %v\n" 到控制台
// 使用 result.GetValue() 和 result.GetReason().Error() 作为 Printf 函数的参数
// Use the Printf function to output "finally 1 error, but then is called. value: %v, error: %v\n" to the console
// Use result.GetValue() and result.GetReason().Error() as the parameters of the Printf function
fmt.Printf("finally 1 error, but then is called. value: %v, error: %v\n", result.GetValue(), result.GetReason().Error())
// 输出 "========== finally 2 successfully ==========" 到控制台
// Print "========== finally 2 successfully ==========" to the console
fmt.Println("========== finally 2 successfully ==========")
// 这是一个被拒绝的 promise
// This is a rejected promise
result = vl.NewPromise(func(resolve func(interface{}, error), reject func(interface{}, error)) {
// 这个 promise 被拒绝,原因是 "error"
// This promise is rejected with the reason "error"
reject(nil, fmt.Errorf("error"))
}).Then(func(value interface{}) (interface{}, error) {
// 如果 promise 被解析,我们将解析的值加上 " vowlink !!"
// If the promise is resolved, we append " vowlink !!" to the resolved value
return value.(string) + " vowlink !!", nil
}, nil).Catch(func(err error) (interface{}, error) {
// 如果 promise 被拒绝,我们将返回一个新的错误信息 "rejected."
// If the promise is rejected, we return a new error message "rejected."
return nil, fmt.Errorf("rejected.")
}).Finally(func() error {
// 不论 promise 是被解析还是被拒绝,Finally 方法都会被调用,并打印 "finally 2"
// Whether the promise is resolved or rejected, the Finally method will be called and print "finally 2"
fmt.Println("finally 2")
// 返回 nil 表示 Finally 方法执行成功
// Return nil indicates that the Finally method was executed successfully
return nil
})
// 使用 Printf 函数输出 "finally 2 is called. value: %v, error: %v\n" 到控制台
// 使用 result.GetValue() 和 result.GetReason() 作为 Printf 函数的参数
// Use the Printf function to output "finally 2 is called. value: %v, error: %v\n" to the console
// Use result.GetValue() and result.GetReason() as the parameters of the Printf function
fmt.Printf("finally 2 is called. value: %v, error: %v\n", result.GetValue(), result.GetReason())
// 输出 "========== finally 2 error ==========" 到控制台
// Print "========== finally 2 error ==========" to the console
fmt.Println("========== finally 2 error ==========")
// 这是一个被拒绝的 promise,Finally 方法中返回了一个错误信息
// This is a rejected promise, and an error message is returned in the Finally method
result = vl.NewPromise(func(resolve func(interface{}, error), reject func(interface{}, error)) {
// 这个 promise 被拒绝,原因是 "error"
// This promise is rejected with the reason "error"
reject(nil, fmt.Errorf("error"))
}).Then(func(value interface{}) (interface{}, error) {
// 如果 promise 被解析,我们将解析的值加上 " vowlink !!"
// If the promise is resolved, we append " vowlink !!" to the resolved value
return value.(string) + " vowlink !!", nil
}, nil).Catch(func(err error) (interface{}, error) {
// 如果 promise 被拒绝,我们将返回一个新的错误信息 "rejected."
// If the promise is rejected, we return a new error message "rejected."
return nil, fmt.Errorf("rejected.")
}).Finally(func() error {
// Finally 函数会在 Promise 完成(无论解决还是拒绝)后被调用
// The Finally function will be called after the Promise is settled (either resolved or rejected)
// 输出 "finally error: 2" 到控制台
// Print "finally error: 2" to the console
fmt.Println("finally error: 2")
// 返回一个新的错误 "error in finally 2"
// Return a new error "error in finally 2"
return errors.New("error in finally 2")
}).Then(func(data interface{}) (interface{}, error) {
// 当 Promise 被解决时,会执行这个 Then 函数
// This Then function will be executed when the Promise is resolved
// 返回解决的值,将会被下一个 Then 函数接收
// Return the resolved value, which will be received by the next Then function
return data.(string) + " vowlink", nil
}, func(reason error) (interface{}, error) {
// 当 Promise 被拒绝时,会执行这个 Catch 函数
// This Catch function will be executed when the Promise is rejected
// 返回一个新的错误 "Handled error: " 加上原因的错误信息
// Return a new error "Handled error: " plus the error message of the reason
return nil, errors.New("Handled error: " + reason.Error())
})
// 使用 Printf 函数输出 "finally 2 error, but then is called. value: %v, error: %v\n" 到控制台
// 使用 result.GetValue() 和 result.GetReason().Error() 作为 Printf 函数的参数
// Use the Printf function to output "finally 2 error, but then is called. value: %v, error: %v\n" to the console
// Use result.GetValue() and result.GetReason().Error() as the parameters of the Printf function
fmt.Printf("finally 2 error, but then is called. value: %v, error: %v\n", result.GetValue(), result.GetReason().Error())
}
Result
$ go run demo.go
========== finally 1 successfully ==========
finally 1
finally 1 is called. value: hello world vowlink !!, error: <nil>
========== finally 1 error ==========
finally error: 1
finally 1 error, but then is called. value: <nil>, error: Handled error: error in finally 1
========== finally 2 successfully ==========
finally 2
finally 2 is called. value: <nil>, error: rejected.
========== finally 2 error ==========
finally error: 2
finally 2 error, but then is called. value: <nil>, error: Handled error: error in finally 2
Yes, you can return a new promise using the then()
method.
Example
package main
import (
"fmt"
vl "github.com/shengyanli1982/vowlink"
)
func main() {
// vowlink 像一个链条,你可以在链条上添加更多的 then() 来在 promise 解析后做更多的事情。
// vowlink is like a chain, you can add more then() to the chain to do more things after the promise is resolved.
result := vl.NewPromise(func(resolve func(interface{}, error), reject func(interface{}, error)) {
// 这个 promise 直接解析为 "hello world"
// This promise is directly resolved to "hello world"
resolve("hello world", nil)
}).Then(func(value interface{}) (interface{}, error) {
// 在 Then 方法中,我们创建一个新的 promise,将解析的值加上 " vowlink(NewPromise)"
// In the Then method, we create a new promise, appending " vowlink(NewPromise)" to the resolved value
return vl.NewPromise(func(resolve func(interface{}, error), reject func(interface{}, error)) {
resolve(value.(string)+" vowlink(NewPromise)", nil)
}), nil
}, nil).Then(func(value interface{}) (interface{}, error) {
// 在这个 Then 方法中,我们获取前一个 promise 的值,并加上 " !!"
// In this Then method, we get the value from the previous promise and append " !!"
return value.(*vl.Promise).GetValue().(string) + " !!", nil
}, nil)
// 从 promise 中获取值并打印
// Get the value from the promise and print it
fmt.Println(result.GetValue())
}
Result
$ go run demo.go
hello world vowlink(NewPromise) !!
To perform an action after all promises are resolved, you can use the all()
method.
Example
package main
import (
"fmt"
vl "github.com/shengyanli1982/vowlink"
)
func main() {
// 创建 3 个 promise
// Create 3 promises
p1 := vl.NewPromise(func(resolve func(interface{}, error), reject func(interface{}, error)) {
// 第一个 promise 直接解析为 "Promise"
// The first promise is directly resolved to "Promise"
resolve("Promise", nil)
}).Then(func(value interface{}) (interface{}, error) {
// 在 Then 方法中,将解析的值加上 " 1"
// In the Then method, append " 1" to the resolved value
return value.(string) + " 1", nil
}, nil)
p2 := vl.NewPromise(func(resolve func(interface{}, error), reject func(interface{}, error)) {
// 第二个 promise 直接解析为 "Promise"
// The second promise is directly resolved to "Promise"
resolve("Promise", nil)
}).Then(func(value interface{}) (interface{}, error) {
// 在 Then 方法中,将解析的值加上 " 2"
// In the Then method, append " 2" to the resolved value
return value.(string) + " 2", nil
}, nil)
p3 := vl.NewPromise(func(resolve func(interface{}, error), reject func(interface{}, error)) {
// 第三个 promise 直接解析为 "Promise"
// The third promise is directly resolved to "Promise"
resolve("Promise", nil)
}).Then(func(value interface{}) (interface{}, error) {
// 在 Then 方法中,将解析的值加上 " 3"
// In the Then method, append " 3" to the resolved value
return value.(string) + " 3", nil
}, nil)
// All() 将等待所有的 promise 被解析,并返回一个带有所有值的 promise
// All() will wait for all promises to be resolved, and return a promise with all the values
result := vl.All(p1, p2, p3)
// 从 promise 中获取所有的值并打印
// Get all the values from the promise and print them
for i, str := range result.GetValue().([]interface{}) {
fmt.Println(">>", i, str.(string))
}
}
Result
$ go run demo.go
>> 0 Promise 1
>> 1 Promise 2
>> 2 Promise 3
I want to use race()
to perform an action once the first promise is resolved.
Example
package main
import (
"fmt"
vl "github.com/shengyanli1982/vowlink"
)
func main() {
// 创建 3 个 promise
// Create 3 promises
p1 := vl.NewPromise(func(resolve func(interface{}, error), reject func(interface{}, error)) {
// 第一个 promise 直接解析为 "Promise"
// The first promise is directly resolved to "Promise"
resolve("Promise", nil)
}).Then(func(value interface{}) (interface{}, error) {
// 在 Then 方法中,将解析的值加上 " 1"
// In the Then method, append " 1" to the resolved value
return value.(string) + " 1", nil
}, nil)
p2 := vl.NewPromise(func(resolve func(interface{}, error), reject func(interface{}, error)) {
// 第二个 promise 直接解析为 "Promise"
// The second promise is directly resolved to "Promise"
resolve("Promise", nil)
}).Then(func(value interface{}) (interface{}, error) {
// 在 Then 方法中,将解析的值加上 " 2"
// In the Then method, append " 2" to the resolved value
return value.(string) + " 2", nil
}, nil)
p3 := vl.NewPromise(func(resolve func(interface{}, error), reject func(interface{}, error)) {
// 第三个 promise 直接解析为 "Promise"
// The third promise is directly resolved to "Promise"
resolve("Promise", nil)
}).Then(func(value interface{}) (interface{}, error) {
// 在 Then 方法中,将解析的值加上 " 3"
// In the Then method, append " 3" to the resolved value
return value.(string) + " 3", nil
}, nil)
// Race() 将等待第一个 promise 被解析,并返回一个带有值的 promise
// Race() will wait for the first promise to be resolved, and return a promise with the value
result := vl.Race(p1, p2, p3)
// 从 promise 中获取值并打印
// Get the value from the promise and print it
fmt.Println(">>", result.GetValue().(string))
}
Result
$ go run demo.go
>> Promise 1
I want to use any()
to perform an action once the first promise is resolved. any()
is similar to race
in ES6. However, any()
also captures any errors from all promises and returns an AggregateError
if all promises are rejected.
Example
package main
import (
"errors"
"fmt"
vl "github.com/shengyanli1982/vowlink"
)
func main() {
// 创建 3 个 promise
// Create 3 promises
p1 := vl.NewPromise(func(resolve func(interface{}, error), reject func(interface{}, error)) {
// 第一个 promise 直接解析为 "Promise"
// The first promise is directly resolved to "Promise"
resolve("Promise", nil)
}).Then(func(value interface{}) (interface{}, error) {
// 在 Then 方法中,将解析的值加上 " 1"
// In the Then method, append " 1" to the resolved value
return value.(string) + " 1", nil
}, nil)
p2 := vl.NewPromise(func(resolve func(interface{}, error), reject func(interface{}, error)) {
// 第二个 promise 直接解析为 "Promise"
// The second promise is directly resolved to "Promise"
resolve("Promise", nil)
}).Then(func(value interface{}) (interface{}, error) {
// 在 Then 方法中,将解析的值加上 " 2"
// In the Then method, append " 2" to the resolved value
return value.(string) + " 2", nil
}, nil)
p3 := vl.NewPromise(func(resolve func(interface{}, error), reject func(interface{}, error)) {
// 第三个 promise 直接解析为 "Promise"
// The third promise is directly resolved to "Promise"
resolve("Promise", nil)
}).Then(func(value interface{}) (interface{}, error) {
// 在 Then 方法中,将解析的值加上 " 3"
// In the Then method, append " 3" to the resolved value
return value.(string) + " 3", nil
}, nil)
// Any() 将等待第一个 promise 被解析,并返回一个带有值的 promise
// Any() will wait for the first promise to be resolved, and return a promise with the value
result := vl.Any(p1, p2, p3)
// 从 promise 中获取值并打印
// Get the value from the promise and print it
fmt.Println(">>", result.GetValue().(string))
// 创建 3 个 promise
// Create 3 promises
p1 = vl.NewPromise(func(resolve func(interface{}, error), reject func(interface{}, error)) {
// 第一个 promise 被拒绝,原因是 "Promise 1 rejected"
// The first promise is rejected with the reason "Promise 1 rejected"
reject(nil, errors.New("Promise 1 rejected"))
})
p2 = vl.NewPromise(func(resolve func(interface{}, error), reject func(interface{}, error)) {
// 第二个 promise 被拒绝,原因是 "Promise 2 rejected"
// The second promise is rejected with the reason "Promise 2 rejected"
reject(nil, errors.New("Promise 2 rejected"))
})
p3 = vl.NewPromise(func(resolve func(interface{}, error), reject func(interface{}, error)) {
// 第三个 promise 被拒绝,原因是 "Promise 3 rejected"
// The third promise is rejected with the reason "Promise 3 rejected"
reject(nil, errors.New("Promise 3 rejected"))
})
// Any() 将等待所有的 promise 被拒绝,并返回一个带有原因 `AggregateError` 的 promise
// Any() will wait for all promises to be rejected, and return a promise with the reason `AggregateError`
result = vl.Any(p1, p2, p3)
// 从 promise 中获取原因并打印
// Get the reason from the promise and print it
fmt.Println("!!", result.GetReason().Error())
}
Result
$ go run demo.go
>> Promise 1
!! All promises were rejected: Promise 1 rejected, Promise 2 rejected, Promise 3 rejected
To perform an action after all promises are resolved or rejected, you can use the allSettled()
method.
Example
package main
import (
"errors"
"fmt"
vl "github.com/shengyanli1982/vowlink"
)
func main() {
// 创建 3 个 promise
// Create 3 promises
p1 := vl.NewPromise(func(resolve func(interface{}, error), reject func(interface{}, error)) {
// 第一个 promise 直接解析为 "Promise 1"
// The first promise is directly resolved to "Promise 1"
resolve("Promise 1", nil)
})
p2 := vl.NewPromise(func(resolve func(interface{}, error), reject func(interface{}, error)) {
// 第二个 promise 被拒绝,原因是 "Promise 2 rejected"
// The second promise is rejected with the reason "Promise 2 rejected"
reject(nil, errors.New("Promise 2 rejected"))
})
p3 := vl.NewPromise(func(resolve func(interface{}, error), reject func(interface{}, error)) {
// 第三个 promise 直接解析为 "Promise 3"
// The third promise is directly resolved to "Promise 3"
resolve("Promise 3", nil)
})
// AllSettled() 将等待所有的 promise 被解析或拒绝,并返回一个带有值的 promise
// AllSettled() will wait for all promises to be resolved or rejected, and return a promise with the value
result := vl.AllSettled(p1, p2, p3)
// 从 promise 中获取所有的结果
// Get all the results from the promise
for i, r := range result.GetValue().([]interface{}) {
// 如果结果是一个错误,打印错误信息
// If the result is an error, print the error message
if v, ok := r.(error); ok {
fmt.Println("!!", i, v.Error())
} else {
// 否则,打印结果值
// Otherwise, print the result value
fmt.Println(">>", i, r.(string))
}
}
}
Result
$ go run demo.go
>> 0 Promise 1
!! 1 Promise 2 rejected
>> 2 Promise 3
After creating a Promise object, you can use the reject
function to trigger an error. Subsequent catch()
functions will handle the previous error and return a new one, creating a chain of error calls.
package main
import (
"errors"
"fmt"
vl "github.com/shengyanli1982/vowlink"
)
func main() {
// 创建一个新的 Promise
// Create a new Promise
result := vl.NewPromise(func(resolve func(interface{}, error), reject func(interface{}, error)) {
// 这个 Promise 会立即被拒绝,原因是 "rejected.100"
// This Promise will be immediately rejected with the reason "rejected.100"
reject(nil, fmt.Errorf("rejected.100"))
}).Catch(func(err error) (interface{}, error) {
// 当 Promise 被拒绝时,会执行这个 Catch 函数
// This Catch function will be executed when the Promise is rejected
fmt.Println("> catch 1")
// 返回一个新的错误,将会被下一个 Catch 函数接收
// Return a new error, which will be received by the next Catch function
return nil, err
}).Catch(func(err error) (interface{}, error) {
// 当上一个 Catch 函数返回错误时,会执行这个 Catch 函数
// This Catch function will be executed when the previous Catch function returns an error
fmt.Println("> catch 2")
// 返回一个新的错误,将会被下一个 Catch 函数接收
// Return a new error, which will be received by the next Catch function
return nil, errors.New("rejected.200")
}).Catch(func(err error) (interface{}, error) {
// 当上一个 Catch 函数返回错误时,会执行这个 Catch 函数
// This Catch function will be executed when the previous Catch function returns an error
fmt.Println("> catch 3")
// 返回一个新的错误,将会被下一个 Catch 函数接收
// Return a new error, which will be received by the next Catch function
return nil, errors.New("rejected.300")
}).Then(func(value interface{}) (interface{}, error) {
// 当 Promise 被解决时,会执行这个 Then 函数
// This Then function will be executed when the Promise is resolved
fmt.Println("> then 1")
// 返回一个新的值,将会被下一个 Then 函数接收
// Return a new value, which will be received by the next Then function
return fmt.Sprintf("Never be here!! recover value: %v", value), nil
}, func(err error) (interface{}, error) {
// 当 Promise 被拒绝时,会执行这个 Catch 函数
// This Catch function will be executed when the Promise is rejected
fmt.Println("> catch 4")
// 返回一个新的错误,将会被下一个 Catch 函数接收
// Return a new error, which will be received by the next Catch function
return nil, errors.New("Should be here.")
})
// 打印 Promise 被拒绝的原因
// Print the reason the Promise was rejected
fmt.Println("reason: ", result.GetReason())
// 打印 Promise 的值,但是在这个例子中,Promise 会被拒绝,所以值会是 nil
// Print the value of the Promise, but in this case, the Promise will be rejected, so the value will be nil
fmt.Println("value: ", result.GetValue())
}
Result
$ go run demo.go
> catch 1
> catch 2
> catch 3
> catch 4
reason: Should be here.
value: <nil>
After creating a Promise object, you can use the reject
function to trigger an error. Each subsequent catch()
function will handle the previous error and return a new one. If a catch()
function successfully recovers from the error and returns a normal value (with error
set to nil
), all subsequent catch()
functions will not be executed. Instead, the then()
function will return this value.
package main
import (
"errors"
"fmt"
vl "github.com/shengyanli1982/vowlink"
)
func main() {
// 创建一个新的 Promise
// Create a new Promise
result := vl.NewPromise(func(resolve func(interface{}, error), reject func(interface{}, error)) {
// 这个 Promise 会立即被拒绝,原因是 "rejected.100"
// This Promise will be immediately rejected with the reason "rejected.100"
reject(nil, fmt.Errorf("rejected.100"))
}).Catch(func(err error) (interface{}, error) {
// 当 Promise 被拒绝时,会执行这个 Catch 函数
// This Catch function will be executed when the Promise is rejected
fmt.Println("> catch 1")
// 返回一个新的错误,将会被下一个 Catch 函数接收
// Return a new error, which will be received by the next Catch function
return nil, err
}).Catch(func(err error) (interface{}, error) {
// 当上一个 Catch 函数返回错误时,会执行这个 Catch 函数
// This Catch function will be executed when the previous Catch function returns an error
fmt.Println("> catch 2")
// 返回一个新的值,将会被下一个 Then 函数接收
// Return a new value, which will be received by the next Then function
return "[error handled]", nil
}).Catch(func(err error) (interface{}, error) {
// 当上一个 Catch 函数返回错误时,会执行这个 Catch 函数
// This Catch function will be executed when the previous Catch function returns an error
fmt.Println("> catch 3")
// 返回一个新的错误,将会被下一个 Catch 函数接收
// Return a new error, which will be received by the next Catch function
return nil, errors.New("rejected.200")
}).Then(func(value interface{}) (interface{}, error) {
// 当 Promise 被解决时,会执行这个 Then 函数
// This Then function will be executed when the Promise is resolved
fmt.Println("> then 1")
// 返回一个新的值,将会被下一个 Then 函数接收
// Return a new value, which will be received by the next Then function
return fmt.Sprintf("Should be here. recover value: %v", value), nil
}, func(err error) (interface{}, error) {
// 当 Promise 被拒绝时,会执行这个 Catch 函数
// This Catch function will be executed when the Promise is rejected
fmt.Println("> catch 4")
// 返回一个新的错误,将会被下一个 Catch 函数接收
// Return a new error, which will be received by the next Catch function
return nil, errors.New("Never be here!!")
})
// 输出 Promise 的拒绝原因,这里一定是 "nil"
// Print the rejection reason of the Promise, it must be "nil" here
fmt.Println("reason: ", result.GetReason())
// 输出 Promise 的解决值,这里一定是 "Should be here."
// Print the resolution value of the Promise, it must be "Should be here." here
fmt.Println("value: ", result.GetValue())
}
Result
$ go run demo.go
> catch 1
> catch 2
> then 1
reason: <nil>
value: Should be here. recover value: [error handled]
After creating a Promise object, the resolve
function is used to handle the normal response, but the resolved value is an error. The then()
function should be used after the Promise to handle the error object and store the result as a value. Subsequent catch()
functions do not respond to this error.
package main
import (
"errors"
"fmt"
vl "github.com/shengyanli1982/vowlink"
)
// 定义 main 函数
// Define the main function
func main() {
// 创建一个新的 Promise
// Create a new Promise
result := vl.NewPromise(func(resolve func(interface{}, error), reject func(interface{}, error)) {
// 这个 Promise 将继续执行,并将错误 "Something went wrong" 作为值传递给下一个 Promise
// This Promise will continue to execute and pass the error "Something went wrong" as a value to the next Promise
resolve(errors.New("Something went wrong"), nil)
}).Then(func(data interface{}) (interface{}, error) {
// 当 Promise 被解决时,会执行这个 Then 函数
// This Then function will be executed when the Promise is resolved
fmt.Println("> then 1")
// 返回错误的字符串表示形式
// Return the string representation of the error
return data.(error).Error(), nil
}, func(error) (interface{}, error) {
// 当 Promise 被拒绝时,会执行这个 Catch 函数
// This Catch function will be executed when the Promise is rejected
fmt.Println("> catch 1")
// 返回一个新的错误 "Handled error"
// Return a new error "Handled error"
return nil, errors.New("Handled error")
}).Catch(func(reason error) (interface{}, error) {
// 当 Promise 被拒绝时,会执行这个 Catch 函数
// This Catch function will be executed when the Promise is rejected
fmt.Println("> catch 2")
// 返回一个字符串,表示恢复的值
// Return a string representing the recovered value
return fmt.Sprintf("Recovered value: %v", reason.Error()), nil
})
// 输出 Promise 的拒绝原因
// Print the rejection reason of the Promise
fmt.Println("reason: ", result.GetReason())
// 输出 Promise 的解决值
// Print the resolution value of the Promise
fmt.Println("value: ", result.GetValue())
}
Result
$ go run demo.go
> then 1
reason: <nil>
value: Something went wrong
After creating a Promise object, you can use the reject
function to raise an exception. However, the reject
function does not return an error, but instead returns a value. Only the then()
function handles the value passed by reject
, while subsequent catch()
functions are skipped without any processing.
package main
import (
"errors"
"fmt"
vl "github.com/shengyanli1982/vowlink"
)
func main() {
// 创建一个新的 Promise
// Create a new Promise
result := vl.NewPromise(func(resolve func(interface{}, error), reject func(interface{}, error)) {
// 这个 Promise 将继续执行,并将错误 "Something went wrong" 作为值传递给下一个 Promise
// This Promise will continue to execute and pass the error "Something went wrong" as a value to the next Promise
reject("Something went wrong", nil)
}).Then(func(data interface{}) (interface{}, error) {
// 当 Promise 被解决时,会执行这个 Then 函数
// This Then function will be executed when the Promise is resolved
fmt.Println("> then 1")
// 返回解决的值,将会被下一个 Then 函数接收
// Return the resolved value, which will be received by the next Then function
return data, nil
}, func(error) (interface{}, error) {
// 当 Promise 被拒绝时,会执行这个 Catch 函数
// This Catch function will be executed when the Promise is rejected
fmt.Println("> catch 1")
// 返回一个新的错误 "Handled error"
// Return a new error "Handled error"
return nil, errors.New("Handled error")
}).Catch(func(reason error) (interface{}, error) {
// 当 Promise 被拒绝时,会执行这个 Catch 函数
// This Catch function will be executed when the Promise is rejected
fmt.Println("> catch 2")
// 返回一个字符串,表示恢复的值
// Return a string representing the recovered value
return fmt.Sprintf("Recovered value: %v", reason.Error()), nil
})
// 输出 Promise 的拒绝原因
// Print the rejection reason of the Promise
fmt.Println("reason: ", result.GetReason())
// 输出 Promise 的解决值
// Print the resolution value of the Promise
fmt.Println("value: ", result.GetValue())
}
Result
$ go run demo.go
> then 1
reason: <nil>
value: Something went wrong