github.com/angenalZZZ/gofunc@v0.0.0-20210507121333-48ff1be3917b/http/longpoll/examples/basic/basic.go (about) 1 // This is a basic example of how to use longpoll. 2 // 3 // In this example, we'll generate some random events and provide a way for 4 // browsers to subscribe to those events. 5 // 6 // To run this example: 7 // go build examples/basic/basic.go 8 // Then run the binary and visit http://127.0.0.1:8081/basic 9 // 10 // A couple of notes: 11 // - In this example, event payloads are string data, but they can be anything 12 // that is convert-able to JSON (passes encoding/json's Marshal() function) 13 // 14 // - LongpollManager.SubscriptionHandler is directly bound to a http handler. 15 // But there's no reason why you can't wrap that handler in your own 16 // function to add a layer of validation, access control, or whatever else 17 // you can think up. See the advanced example on how to do this. 18 // 19 // - Our events are simple and randomly generated in a goroutine, but you can 20 // create events anywhere and anyhow as long as you pass a reference to the 21 // LongpollManager and just call Publish(). Maybe you have a goroutine that 22 // checks the weather, a stock price, or something cool. Or you can even 23 // have another http handler that calls Publish(). To do this, you must 24 // capture the manager reference in a closure. See the advanced example. 25 // 26 package main 27 28 import ( 29 "fmt" 30 "github.com/angenalZZZ/gofunc/http/longpoll" 31 "log" 32 "math/rand" 33 "net/http" 34 "time" 35 ) 36 37 func main() { 38 manager, err := longpoll.StartLongpoll(longpoll.Options{ 39 LoggingEnabled: true, 40 // NOTE: if not defined here, other options have reasonable defaults, 41 // so no need specifying options you don't care about 42 }) 43 if err != nil { 44 log.Fatalf("Failed to create manager: %q", err) 45 } 46 // pump out random events 47 go generateRandomEvents(manager) 48 // Serve our basic example driver webpage 49 http.HandleFunc("/basic", BasicExampleHomepage) 50 51 // Serve our event subscription web handler 52 http.HandleFunc("/basic/events", manager.SubscriptionHandler) 53 54 fmt.Println("Serving webpage at http://127.0.0.1:8081/basic") 55 http.ListenAndServe("127.0.0.1:8081", nil) 56 57 // We'll never get here as long as http.ListenAndServe starts successfully 58 // because it runs until you kill the program (like pressing Control-C) 59 // Buf if you make a stoppable http server, or want to shut down the 60 // internal longpoll manager for other reasons, you can do so via 61 // Shutdown: 62 manager.Shutdown() // Stops the internal goroutine that provides subscription behavior 63 // Again, calling shutdown is a bit silly here since the goroutines will 64 // exit on main() exit. But I wanted to show you that it is possible. 65 } 66 67 func generateRandomEvents(lpManager *longpoll.LongpollManager) { 68 farm_events := []string{ 69 "Cow says 'Moooo!'", 70 "Duck went 'Quack!'", 71 "Chicken says: 'Cluck!'", 72 "Goat chewed grass.", 73 "Pig went 'Oink! Oink!'", 74 "Horse ate hay.", 75 "Tractor went: Vroom Vroom!", 76 "Farmer ate bacon.", 77 } 78 // every 0-5 seconds, something happens at the farm: 79 for { 80 time.Sleep(time.Duration(rand.Intn(5000)) * time.Millisecond) 81 lpManager.Publish("farm", farm_events[rand.Intn(len(farm_events))]) 82 } 83 } 84 85 // Here we're providing a webpage that shows events as they happen. 86 // In this code you'll see a sample of how to implement longpolling on the 87 // client side in javascript. I used jquery here... 88 // 89 // I was too lazy to serve this file statically. 90 // This is me setting a bad example :) 91 func BasicExampleHomepage(w http.ResponseWriter, r *http.Request) { 92 fmt.Fprintf(w, ` 93 <html> 94 <head> 95 <title>golongpoll basic example</title> 96 </head> 97 <body> 98 <h1>golongpoll basic example</h1> 99 <h2>Here's whats happening around the farm:</h2> 100 <ul id="animal-events"></ul> 101 <script src="http://code.jquery.com/jquery-1.11.3.min.js"></script> 102 <script> 103 104 // for browsers that don't have console 105 if(typeof window.console == 'undefined') { window.console = {log: function (msg) {} }; } 106 107 // Start checking for any events that occurred after page load time (right now) 108 // Notice how we use .getTime() to have num milliseconds since epoch in UTC 109 // This is the time format the longpoll server uses. 110 var sinceTime = (new Date(Date.now())).getTime(); 111 112 // Let's subscribe to animal related events. 113 var category = "farm"; 114 115 (function poll() { 116 var timeout = 45; // in seconds 117 var optionalSince = ""; 118 if (sinceTime) { 119 optionalSince = "&since_time=" + sinceTime; 120 } 121 var pollUrl = "/basic/events?timeout=" + timeout + "&category=" + category + optionalSince; 122 // how long to wait before starting next longpoll request in each case: 123 var successDelay = 10; // 10 ms 124 var errorDelay = 3000; // 3 sec 125 $.ajax({ url: pollUrl, 126 success: function(data) { 127 if (data && data.events && data.events.length > 0) { 128 // got events, process them 129 // NOTE: these events are in chronological order (oldest first) 130 for (var i = 0; i < data.events.length; i++) { 131 // Display event 132 var event = data.events[i]; 133 $("#animal-events").append("<li>" + event.data + " at " + (new Date(event.timestamp).toLocaleTimeString()) + "</li>") 134 // Update sinceTime to only request events that occurred after this one. 135 sinceTime = event.timestamp; 136 } 137 // success! start next longpoll 138 setTimeout(poll, successDelay); 139 return; 140 } 141 if (data && data.timeout) { 142 console.log("No events, checking again."); 143 // no events within timeout window, start another longpoll: 144 setTimeout(poll, successDelay); 145 return; 146 } 147 if (data && data.error) { 148 console.log("Error response: " + data.error); 149 console.log("Trying again shortly...") 150 setTimeout(poll, errorDelay); 151 return; 152 } 153 // We should have gotten one of the above 3 cases: 154 // either nonempty event data, a timeout, or an error. 155 console.log("Didn't get expected event data, try again shortly..."); 156 setTimeout(poll, errorDelay); 157 }, dataType: "json", 158 error: function (data) { 159 console.log("Error in ajax request--trying again shortly..."); 160 setTimeout(poll, errorDelay); // 3s 161 } 162 }); 163 })(); 164 </script> 165 </body> 166 </html>`) 167 }