我假設長時間運行的任務正在被客戶端啓動。 因此,在你開始任務之前,請從客戶端發出一個ajax請求到類似於這個的處理程序。這個處理程序有兩件事返回給客戶端。 javascript api用於創建頻道的令牌參數以及用於確定哪個客戶端創建頻道的cid param。
from google.appengine.api import channel
@ae.route("/channel")
class CreateChannel(webapp2.RequestHandler):
def get(self):
cid = str(uuid.uuid4())
token = channel.create_channel(cid)
data = {
"cid":cid,
"token":token
}
self.response.write(json.dumps(data))
現在使用JavaScript API來創建一個新的通道 https://cloud.google.com/appengine/docs/python/channel/javascript
var onClosed = function(resp){
console.log("channel closed");
};
var onOpened = function(resp){
console.log("channel created");
};
var onmessage = function(resp){
console.log("The client received a message from the backend task");
console.log(resp);
};
var channel_promise = $.ajax({
url: "/channel",
method: "GET"
});
channel_promise.then(function(resp){
//this channel id is important you need to get it to the backend process so it knows which client to send the message to.
var client_id = resp.data.cid;
var channel = new goog.appengine.Channel(resp.data.token);
handler = {
'onopen': $scope.onOpened,
'onmessage': $scope.onMessage,
'onerror': function() {
},
'onclose': function() {
alert("channel closed.")
}
};
socket = channel.open(handler);
//onOpened is the callback function to call after channel has been created
socket.onopen = onOpened;
//onClose is the callback function to call after channel has been closed
socket.onclose = onClosed;
//onmessage is the callback function to call when receiving messages from your task queue
socket.onmessage = onMessage;
});
現在,我們都設置爲偵聽信道消息的通道。 所以當用戶點擊按鈕時,我們需要啓動後端任務。
var letsDoSomeWorkOnClick = function(){
//make sure you pass the client id with every ajax request
$.ajax({
url: "/kickoff",
method: "POST",
params: {"cid":client_id}
});
}
現在應用引擎處理程序啓動後端任務隊列。我使用緩衝庫來執行此操作。 https://cloud.google.com/appengine/articles/deferred
@ae.route("/kickoff")
KickOffHandler(webapp2.RequestHandler):
def post(self):
cid = self.request.get("cid")
req = {}
req['cid'] = cid
task = MyLongRunningTask()
deferred.defer(task.long_runner_1, req, _queue="my-queue")
例如任務:
class MyLongRunningTask:
def long_runner_1(self,req):
# do a whole bunch of stuff
channel.send_message(req["cid"], json.dumps({"test":"letting client know task is done"})
對不起,我相信你誤解了我的問題。這裏的問題是,我怎樣才能將相同的消息發送給連接到應用程序的許多客戶端(因爲Google不允許這樣做) –
噢,是的,我確實想過要發送郵件給特定的客戶。我的錯。 – bscott
我感到尷尬,因爲你寫了一個全面的完整答案:/ –