duanmen1887
2019-02-20 16:48
采纳率: 0%
浏览 9
已采纳

如何使我的函数立即返回Slack?

I'm trying to develop a simple API for Slack and I want to return something to the user right away to avoid the 3000 ms timeout.

Here are my questions:

  1. Why the This should be printed to Slack first doesn't get printed right away, instead I only got the last message which is The long and blocking process completed? But it appears in ngrok log though.

  2. Why is my function still reaching the 3000 ms limit even though I'm already using a go routine? Is it because of the done channel?

func testFunc(w http.ResponseWriter, r *http.Request) {
    // Return to the user ASAP to avoid 3000ms timeout.
    // But this doesn't work. Nothing is returned but
    // the message appeared in ngrok log.
    fmt.Fprintln(w, "This should be printed to Slack first!")

    // Get the response URL.
    r.ParseForm()
    responseURL := r.FormValue("response_url")

    done := make(chan bool)

    go func() {
        fmt.Println("Warning! This is a long and blocking process.")
        time.Sleep(5 * time.Second)

        done <- true
    }()

    // This works! I received this message. But I still reached the 3000ms timeout.
    func(d bool) {
        if d == true {
            payload := map[string]string{"text": "The long and blocking process completed!"}
            j, err := json.Marshal(payload)

            if err != nil {
                w.WriteHeader(http.StatusInternalServerError)
            }

            http.Post(responseURL, "application/json", bytes.NewBuffer(j))
        }
    }(<-done)
}
  • 写回答
  • 好问题 提建议
  • 关注问题
  • 收藏
  • 邀请回答

2条回答 默认 最新

  • dpzo13732 2019-02-20 17:06
    已采纳

    http.ResponseWriter streams are buffered by default. If you want data to be sent to a client in realtime (e.g. HTTP SSE), you need to flush the stream after each 'event':

    wf, ok := w.(http.Flusher)
    
    if !ok {
        http.Error(w, "Streaming unsupported!", http.StatusInternalServerError)
        return
    }
    
    fmt.Fprintln(w, "This should be printed to Slack first!")
    
    wf.Flush()
    

    Flushing is expensive - so take advantage of go's buffering. There will always be an implicit flush once your handler finally exits (hence why you saw your output 'late').

    已采纳该答案
    评论
    解决 无用
    打赏 举报
  • douyan4900 2019-02-20 17:05

    I am learning stage of golang. Here is my understanding: 1. any operations with channel is blocking 2. You are writing on the channel in the

        go func() {
            fmt.Println("Warning! This is a long and blocking process.")
            time.Sleep(5 * time.Second)
    
            done <- true
        }()
    
    1. The scheduler is still moving in the main function and trying to read from the channel but it is waiting to see, something has written on the channel or not. So it got blocked, when the above function is done with writing on the channel, controls came back and main start executing again.

    Note: Experts will be able to explain better.

    评论
    解决 无用
    打赏 举报

相关推荐 更多相似问题