Skip to content

Promise 的 Golang 实现,其行为符合 Promises/A+ 规范,并参考 Promise ES 规范实现,尽可能模拟了 JavaScript 事件循环中 Promise 的行为。

License

Notifications You must be signed in to change notification settings

TikaFlow/promise-go

Repository files navigation

Promise-Go

PromiseGolang实现,其行为符合Promises/A+规范,并参考Promise ES规范实现,尽可能模拟了JavaScript事件循环中Promise的行为。

项目概述

Promise-Go提供了一个完整的异步编程解决方案,允许开发者以链式调用的方式处理异步操作,具有以下特点:

  • 完全符合Promises/A+规范
  • 支持Promise ES规范中的常用方法
  • 模拟JavaScript事件循环机制(宏任务和微任务队列)
  • 提供丰富的Promise组合方法(AllAllSettledAnyRace等)
  • 实现Stringer接口,支持直接打印Promise实例状态
  • 提供定时器相关功能(SetTimeoutSetInterval等)

目录

快速开始

以下是一个简单的示例,展示如何创建和使用Promise

安装

使用Go模块系统安装Promise-Go

go get github.com/TikaFlow/promise-go

导入

import "github.com/TikaFlow/promise-go"

使用示例

package main

import "github.com/TikaFlow/promise-go"

func main() {
    // 推荐将 Promise 相关代码包装为异步任务,更符合事件循环机制
    promise.Async(func() {
        // 创建一个成功的 Promise
        p := promise.New(func(resolve, reject func(v any)) (err error) {
            // 模拟异步操作
            promise.SetTimeout(func() {
                resolve("操作成功完成")
            }, 1000)
            return
        })
        
        // 处理 Promise
        p.Then(func(v any) (any, error) {
            println("成功:", v.(string))
            return v, nil
        }, func(reason any) (any, error) {
            println("失败:", reason)
            return nil, nil
        })
    })

    // 等待事件循环结束,避免 main 函数提前退出
	<-promise.Done()
}

核心接口

完整API

请参考API文档获取完整的函数列表和详细说明。

Promise 接口

// Promise 是一个拥有 then 方法的对象,其行为符合 Promises/A+ 规范
type Promise interface {
    // State 返回 Promise 的当前状态
    State() string
    
    // Result 返回 Promise 的结果值
    Result() any
    
    // Done 返回一个通道,当 Promise 状态变为 Fulfilled 或 Rejected 时,该通道会被关闭
    Done() chan struct{}
    
    // Then 方法返回一个新的 Promise,其状态和结果值由回调函数的执行结果决定
    Then(onFulfilled, onRejected ThenCallback) Promise
    
    // Catch 方法返回一个新的 Promise,是 Then(nil, onRejected) 的语法糖
    Catch(onRejected ThenCallback) Promise
    
    // Finally 方法返回一个新的 Promise,其状态和结果值与原 Promise 相同
    Finally(onFinally FinallyCallback) Promise
}

主要函数

Promise 创建函数

// New 创建一个新的 Promise 实例
func New(exec Executor) Promise

// Resolve 返回一个已解决的 Promise
func Resolve(value any) Promise

// Reject 返回一个已拒绝的 Promise
func Reject(reason any)

Promise 组合函数

// All 等待所有 Promise 解决
func All(proms ...any) Promise

// AllSettled 等待所有 Promise 完成(无论成功失败)
func AllSettled(proms ...any) Promise

// Any 等待第一个 Promise 解决
func Any(proms ...any) Promise

// Race 等待第一个 Promise 完成
func Race(proms ...any) Promise

典型示例

基础用法

创建 Promise

// 创建一个立即解决的 Promise
p := promise.New(func(resolve, reject func(v any)) (err error) {
    resolve("hello world")
    return
})

链式调用

p := promise.New(func(resolve, reject func(v any)) (err error) {
    resolve("hello world")
    return
})

p.Then(func(v any) (any, error) {
    println(v.(string))  // 输出: hello world
    return v, nil
}, nil).Then(func(v any) (any, error) {
    println(v.(string))  // 输出: hello world
    return v, nil
}, nil).Catch(func(err any) (any, error) {
    println("捕获到错误:", err)
    return nil, nil
}).Finally(func() (any, error) {
    println("无论成功失败都会执行")
    return nil, nil
})

更多示例

更多完整的示例可以参考项目中的示例文件:

注意事项

事件循环管理

程序退出管理

在长时间运行的程序中,应首先调用EventLoopHandler()获取事件循环句柄,以免事件循环因空闲超时而被动退出。 并在程序结束前调用该句柄的Close()方法主动结束事件循环。

如果不需要长时间运行,或不需要主动结束事件循环,则可以不调用EventLoopHandler(), 而是通过Done()获取关闭信号的通道,等待通道关闭。

// 短时间运行的程序,无需主动关闭事件循环
func main() {
    // 创建一个 Promise
    p := promise.New(func(resolve, reject func(v any)) (err error) {
        // 模拟异步操作
        promise.SetTimeout(func() {
            resolve("操作完成")
        }, 2000)
        return
    })

    // 等待事件循环关闭
    <-promise.Done()
    println("Promise 完成")
}

// 长时间运行的程序,建议主动关闭事件循环
func main() {
    // 获取事件循环句柄
    elh := promise.EventLoopHandler()
    // 关闭事件循环
    defer elh.Close()

    // 长时间服务循环
    service()
}

超时时间

默认情况下,事件循环的超时时间为512毫秒,并有128毫秒的额外超时保护,即共计640毫秒。如果一个异步任务在640毫秒内未完成, 或空闲时间超过640毫秒,事件循环会被强制退出。

可以通过以下方式延长:

  • 【推荐】获取事件循环操作句柄:将无限延长超时时间(即永不超时),直到手动关闭事件循环。
  • 手动延长超时时间:调用promise.SetTimeout()promise.SetInterval()时,将根据设置的延迟时间自动延长超时时间(一次有效,到期将恢复)。

等待 Promise 完成

<-p.Done()可以等待Promise完成,但需要注意,这会阻塞当前goroutine,直到Promise完成(有可能永远是Pending)。因此应避免使用, 而是使用p.Then()p.Catch()来处理Promise的结果,或调用promise.Await()等待Promise完成。

错误处理

错误传播

Promise链中的错误会自动传播到下一个拒绝处理程序。与在JS中一样,可以在链的末端添加.Catch()以捕获任何未处理的错误。

类型断言

由于Go的类型系统,在处理Promise结果时需要进行类型断言。请确保安全地处理断言可能失败的情况。

p.Then(func(v any) (any, error) {
    // 安全地进行类型断言
    if str, ok := v.(string); ok {
        println("字符串结果:", str)
    } else {
        println("类型错误,不是字符串")
    }
    return v, nil
}, nil)

错误信息

ThenCallbackFinallyCallback回调函数中,如果有报错,请务必将错误信息放入在v中,并在err中放入简单错误信息(也不能为nil)。

这是为了支持任意类型的错误信息,即此时应该返回(detail, summary)格式的错误,而不是(nil, err)

性能考虑

定时器精度

定时器(SetTimeout/SetInterval)的精度依赖于Go运行时和系统调度,不保证毫秒级精确执行及执行顺序。

任务队列大小

大量的微任务或宏任务可能会影响性能,特别是在高并发场景下。请合理使用这些功能。

常见陷阱

错误的返回值

Then(及CatchFinally)回调中使用不正确的报错方式(即返回(nil, err)而不是(detail, summary))会导致后续的Promise链接收nil

阻塞事件循环

Promise执行器或回调中执行耗时操作会阻塞整个事件循环,应避免这样做。

嵌套过多

过多的Promise嵌套会使代码难以理解和维护。尽量使用链式调用或组合函数来扁平化异步流程。

许可证

MIT License

Copyright (c) [2025] [兮夏]

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

About

Promise 的 Golang 实现,其行为符合 Promises/A+ 规范,并参考 Promise ES 规范实现,尽可能模拟了 JavaScript 事件循环中 Promise 的行为。

Topics

Resources

License

Stars

Watchers

Forks

Packages

No packages published

Languages