在REST API中进行异步函数调用

huangapple go评论86阅读模式
英文:

Async function call in REST API

问题

这里有一个函数returnAllArticles,它将被用于REST API的调用,该函数返回一组文章。在这个函数内部,调用了一个异步函数DoneAsync。这个异步函数可能需要一些时间来处理自己的数据。我希望返回一个JSON值,即使异步函数还没有完成。我贴下了代码:

func returnAllArticles(w http.ResponseWriter, r *http.Request){
    fmt.Println("Endpoint Hit: returnAllArticles")
    json.NewEncoder(w).Encode(Articles)
   
    val := DoneAsync()
    fmt.Println("Done is running ...")
    fmt.Println(<- val)
}

func DoneAsync() chan int {
    r := make(chan int)
    fmt.Println("Warming up ...")
    go func() {
        time.Sleep(3 * time.Second)
        r <- 1
        fmt.Println("Done ...")
    }()
    return r
}

func handleRequests() {
    myRouter := mux.NewRouter().StrictSlash(true)
    myRouter.HandleFunc("/articles", returnAllArticles)
    log.Fatal(http.ListenAndServe(":8080", myRouter))
}

但是在我的情况下,直到异步函数完成后,JSON值才会返回。我无法获得异步函数的特性。

英文:

Here I have one function i.e returnAllArticles which will be called for REST API and this function returns a list of articles and inside this function one async function i.e DoneAsync is being called. This aysnc function may take some time to process its own data. I want json value i.e all articles should be returned whether that async function is complete or not. Code I have pasted below

func returnAllArticles(w http.ResponseWriter, r *http.Request){
    fmt.Println(&quot;Endpoint Hit: returnAllArticles&quot;)
    json.NewEncoder(w).Encode(Articles)
   
        val := DoneAsync()
	fmt.Println(&quot;Done is running ...&quot;)
	fmt.Println(&lt;- val)

}

func DoneAsync() chan int {
	r := make(chan int)
	fmt.Println(&quot;Warming up ...&quot;)
	go func() {
		time.Sleep(3 * time.Second)
		r &lt;- 1
		fmt.Println(&quot;Done ...&quot;)
	}()
	return r
}
func handleRequests() {
    myRouter := mux.NewRouter().StrictSlash(true)
    myRouter.HandleFunc(&quot;/articles&quot;, returnAllArticles);
   log.Fatal(http.ListenAndServe(&quot;:8080&quot;,myRouter))
}

But in my case json value is not returning until async func is done. I am not getting asynchronous features for that async function.

答案1

得分: 1

这行代码将会阻塞,直到有一个值被写入到 val 中:

    fmt.Println(<-val)

所以你的 DoneAsync 函数创建了一个 goroutine 来处理某些事情,并最终将结果写入到 val 通道中,但是调用它的处理程序会等待直到有东西被写入到该通道中。

如果你希望在进行处理的同时发送编码结果,你可以检查响应处理程序是否实现了 Flusher 接口,并进行刷新:

if f, ok := w.(http.Flusher); ok {
   f.Flush()
}
英文:

This line will block until a value is written to val:

    fmt.Println(&lt;- val)

So your DoneAsync function creates a goroutine that goes on to process something, and in the end writes to the val channel, but the handler that called it waits until something is written to that channel.

If you want the encoded result to be sent while you're doing this processing, you can when if the response handler implements Flusher, and flush it:

if f, ok:=w.(http.Flusher); ok {
   f.Flush()
}

huangapple
  • 本文由 发表于 2021年7月6日 21:47:21
  • 转载请务必保留本文链接:https://go.coder-hub.com/68271765.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定