如何等待回调函数返回?

时间:2020-06-12 19:43:05

标签: go callback

我有以下代码:

http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
  player.Exec(command, func(response map[string]interface{}){
    if response["statusCode"]==float64(0) { // ok
      w.Write([]byte(response["statusMessage"].(string)))
      player.SendMessage("<b>"+response["statusMessage"].(string)+"</b>")
      fmt.Println("playerExec: "+time.Now().Format("20060102150405"))
    } else { // failed to process
      w.WriteHeader(http.StatusBadRequest) // 400
      w.Write([]byte(response["statusMessage"].(string)))
      player.SendMessage(response["statusMessage"].(string))
    }
  })
  // Time.Sleep(Time.Seconds*2)
  fmt.Println("cmd: "+time.Now().Format("20060102150405"))   
})
player.Exec()

处理需要一些时间(因为它启动了WebSocket连接),因此回调函数会在一段时间后被调用(请参见下面的证明)。已经晚了,所以我看到以下错误:

http:多余的响应。main.main.func1.1中的WriteHeader调用

此外,当我在浏览器中打开“ /”页面时,看不到任何内容。 如果我将Time.Sleep()添加到代码中(请参见注释行),那么我会看到内容。 Exec()代码为here

日志显示以下内容-

cmd: 20200612192659
playerExec: 20200612192659

有什么方法可以等待回调函数返回吗?

2 个答案:

答案 0 :(得分:2)

是的,您可以按以下方式使用sync.WaitGroup

wg := sync.WaitGroup{}

http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
  wg.Add(1)  // add a waitgroup before calling the async function
  player.Exec(command, func(response map[string]interface{}){
    defer wg.Done()  // release when this function returns
    if response["statusCode"]==float64(0) { // ok
      w.Write([]byte(response["statusMessage"].(string)))
      player.SendMessage("<b>"+response["statusMessage"].(string)+"</b>")
      fmt.Println("playerExec: "+time.Now().Format("20060102150405"))
    } else { // failed to process
      w.WriteHeader(http.StatusBadRequest) // 400
      w.Write([]byte(response["statusMessage"].(string)))
      player.SendMessage(response["statusMessage"].(string))
    }
  })
  wg.Wait()  // this will block until all the resources are released
  fmt.Println("cmd: "+time.Now().Format("20060102150405"))   
})

答案 1 :(得分:0)

http:多余的响应。main.main.func1.1中的WriteHeader调用

如果您已经通过WriteHeader向响应中写了一些内容,则执行Write后,您将看到此消息。这就是为什么WriteHeader是多余的或superfluous的原因。

在等待执行结束时,可以在闭包中使用waitgroup。

wg.Wait()将等待,直到您的exec回调返回

http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
  var wg sync.WaitGroup
  wg.Add(1)
  player.Exec(command, func(response map[string]interface{}){
    defer wg.Done()
    if response["statusCode"]==float64(0) { // ok
      w.Write([]byte(response["statusMessage"].(string)))
      player.SendMessage("<b>"+response["statusMessage"].(string)+"</b>")
      fmt.Println("playerExec: "+time.Now().Format("20060102150405"))
    } else { // failed to process
      w.WriteHeader(http.StatusBadRequest) // 400
      w.Write([]byte(response["statusMessage"].(string)))
      player.SendMessage(response["statusMessage"].(string))
    }
  })

  wg.Wait()

  // Time.Sleep(Time.Seconds*2)
  fmt.Println("cmd: "+time.Now().Format("20060102150405"))   
})