通过用户操作取消功能html/模板

问题描述

我的目标是:

前两点是可以的(或者随时告诉我我可以改进的地方)

但是我不知道怎么做第三点(因为我用来做第一点的方法不好?)

    package main
    
    import (
        "html/template"
        "github.com/labstack/echo"
        "log"
        "io"
        "net/http"
        "strconv"
        "fmt"
        "time"
    )
    
    //init LOG
    func init(){
        log.SetPrefix("TRACE: ")
        log.SetFlags(log.Ldate | log.Ltime | log.Llongfile)
        log.Println("init started")
    }
    
    // main function
    func main() {
    
    // defining struct instance
    settings.Enabled = false
    
    // Parsing the required html
    // file in same directory
    // Parsing Templates
    t := &Template{
        templates: template.Must(template.ParseGlob("test.html")),}
    
    // standard output to print merged data
    
    e := echo.New()
    e.Renderer = t
    e.HideBanner = false
    e.HidePort = false
    e.Debug = true
    
    e.GET("/",index)
    e.GET("/toggleEnable",toggleEnable)
    
    e.Start("127.0.0.1" + ":" + strconv.Itoa(8080))
    
    }
    
    func index(c echo.Context) error {
        return c.Render(http.StatusOK,"index",settings)
    } 
    
    // Settings Type ...
    type Settings struct {
        Enabled bool
    }
    var settings Settings
    
    type Template struct {
        templates *template.Template
    }
    
    func (t *Template) Render(w io.Writer,name string,data interface{},c echo.Context) error {
        return t.templates.ExecuteTemplate(w,name,data)
    }
    
    func toggleEnable(c echo.Context) error {
        if settings.Enabled {
            settings.Enabled = false
        } else {
            settings.Enabled = true
            Sum()
        }
        return c.Redirect(http.StatustemporaryRedirect,c.Request().Header.Get("Referer"))
    }
    
    func Sum() {
    
        sum := 0
        for i := 1; i < 50; i++ {
            sum += i
            fmt.Println(sum)
            time.Sleep(3 * time.Second)
        }
    
    }

和 test.html:

``` 
    <!DOCTYPE html> 
    <html> 
       <head> 
          <title>Test</title> 
       </head> 
       <body> 
    {{define "index"}}
          <h1>Settings</h1>
          
             <p>Test enabled : <a href="/toggleEnable">{{.Enabled }}</a></p>
             
    {{end}}
       </body> 
    </html> 

```

目前,如果我假 -> 真:求和有效,如果我是真->假:什么也没有发生,如果我假 -> 再真一次:另一个计数开始。

下一步是在 html 页面显示计数。

解决方法

正如当前编写的,当浏览器请求 /toggleEnable 时,在 Sum() 完成之前不会返回任何内容(大约需要 150 秒)。 Sum() 完成后,带有 Test enabled : false 的页面将被返回/显示。如果您想为用户提供中断进程的能力,那么最好在 Goroutine 中运行它;像这样:

// Settings Type ...
type Settings struct {
    Enabled bool
    Stop chan struct{}
}
var settings Settings

type Template struct {
    templates *template.Template
}

func (t *Template) Render(w io.Writer,name string,data interface{},c echo.Context) error {
    return t.templates.ExecuteTemplate(w,name,data)
}

func toggleEnable(c echo.Context) error {
    if settings.Enabled {
        settings.Enabled = false
        close(settings.Stop)
    } else {
        settings.Enabled = true
        settings.Stop = make(chan struct{})
        go Sum(settings.Stop)
    }
    return c.Redirect(http.StatusTemporaryRedirect,c.Request().Header.Get("Referer"))
}

func Sum(stop chan struct{}) {
    sum := 0
    for i := 1; i < 50; i++ {
        sum += i
        fmt.Println(sum)
        select {
        case <-stop:
            fmt.Println("stopped")
            return
        case <-time.After(3 * time.Second):
        }
    }
}

请注意,这有一些问题。它是在假设只有一个客户端并且计时器完成时页面不会更新的假设下编写的(您需要添加刷新或类似功能)。

下一步是在 html 页面中显示计数

为此,您需要一种让浏览器请求更新的方法。这可以通过 refresh(相当简单但不是很好的用户体验)或使用 Javascript(轮询或使用 websockets)。