我正在使用grpc go
我有一个看起来大致像这样的rpc
<script>
$(function() {
var itm = [];
$( "#savebutton" ).click(function() { LISTOBJ.saveList(); });
$("#myAccordion").accordion({
heightStyle: "content",
active: false,
collapsible: true
});
$("#myAccordion li").draggable({
appendTo: "body",
helper: "clone"
});
$(".leader ol").droppable({
activeClass: "ui-state-default",
hoverClass: "ui-state-hover",
accept: ":not(.ui-sortable-helper)",
drop: function(event, ui) {
var zz = ui.draggable.text()
var xyz = itm.includes(zz);
if (xyz === false) {
$(this).find(".placeholder").remove();
$("<li></li>").text(ui.draggable.text())
//.addClass("cart-item")
.addClass('dropClass')
.appendTo(this);
//add to array
itm.push(zz);
//add style
//$('.ui-droppable').find("li.ui-draggable:contains('" + zz + "')").addClass('bred');
var n = $(this).closest("div.proc").find(".dropClass").length;
$(this).closest("div.proc").find("span").text("Items Dropped: " + n + ".");
} else {
alert('Name is Already Exist');
}
}
}).sortable({
items: "li:not(.placeholder)",
sort: function() {
$(this).removeClass("ui-state-default");
}
});
$(".checker ol").droppable({
activeClass: "ui-state-default",
hoverClass: "ui-state-hover",
accept: ":not(.ui-sortable-helper)",
drop: function(event, ui) {
var zz = ui.draggable.text()
var xyz = itm.includes(zz);
if (xyz === false) {
$(this).find(".placeholder").remove();
$("<li></li>").text(ui.draggable.text())
//.addClass("cart-item")
.addClass('dropClass')
.appendTo(this);
//add to array
itm.push(zz);
//add style
$('.ui-droppable').find("li.ui-draggable:contains('" + zz + "')").addClass('bred');
var n = $(this).closest("div.proc").find(".dropClass").length;
$(this).closest("div.proc").find("span").text("Items Dropped: " + n + ".");
} else {
alert('Name is Already Exist');
}
}
}).sortable({
items: "li:not(.placeholder)",
sort: function() {
$(this).removeClass("ui-state-default");
}
});
$("#myAccordion ul").droppable({
drop: function(event, ui) {
$(ui.draggable).remove();
var zz = ui.draggable.text()
$('.ui-droppable').find("li.ui-draggable:contains('" + zz + "')").removeClass('bred');
var indexItm = itm.indexOf(zz);
if (indexItm > -1) {
itm.splice(indexItm, 1);
}
},
hoverClass: "ui-state-hover"
//accept: '.cart-item'
});
});
var LISTOBJ = {
saveList: function() {
$(".leader").each(function() {
var listCSV = [];
$(this).find("li").each(function(){
listCSV.push($(this).text());
});
var values = listCSV.join(', ');
$(".output").append("<input type='hidden' name='leader[]' value='"+values+"' />");
$("#output").append("<p>"+values+"</p>");
console.debug(listCSV);
});
}
}
</script>
客户端使用grpc.Dial()方法连接
当客户端连接时,服务器会进行一些簿记。当客户断开连接时,需要删除簿记。
是否有任何可以注册的回调可用于知道客户已关闭会话。
答案 0 :(得分:3)
假设服务器是在go中实现的,$(window).scroll(function() {
var height = $(window).scrollTop();
if(height > some_number) {
// change url here
}
});
上有一个API报告连接状态更改。
*grpc.ClientConn
https://godoc.org/google.golang.org/grpc#ClientConn.WaitForStateChange
这些是每个func (cc *ClientConn) WaitForStateChange(ctx context.Context, sourceState connectivity.State) bool
https://github.com/grpc/grpc/blob/master/doc/connectivity-semantics-and-api.md
如果您需要公开一个可以监听客户端关闭连接的频道,则可以执行以下操作:
connectivity.State
如果您只想考虑正在关闭或关闭的连接,则可以这样称呼它:
func connectionOnState(ctx context.Context, conn *grpc.ClientConn, states ...connectivity.State) <-chan struct{} {
done := make(chan struct{})
go func() {
// any return from this func will close the channel
defer close(done)
// continue checking for state change
// until one of break states is found
for {
change := conn.WaitForStateChange(ctx, conn.GetState())
if !change {
// ctx is done, return
// something upstream is cancelling
return
}
currentState := conn.GetState()
for _, s := range states {
if currentState == s {
// matches one of the states passed
// return, closing the done channel
return
}
}
}
}()
return done
}
答案 1 :(得分:2)
根据您的代码,这是一元 rpc 调用,客户端仅连接到服务器一次,发送请求并获得响应。客户端将等待响应直到超时。
在服务器端流式传输中,您可以从客户端断开连接
<-grpc.ServerStream.Context.Done()
信号。
有了上面的内容,您必须在 go 例程中实现您自己的频道来构建您的逻辑。使用 select
语句为:
select {
case <-srv.Context().Done():
return
case res := <-<YOUR OWN CHANNEL, WITH RECEIVED RESQUEST OR YOUR RESPONSE>
....
}
在客户端流中,除了上面的信号,你还可以检查服务器是否可以接收到msg:
req, err := grpc.ServerStream.Recv()
if err == io.EOF {
break
} else if err != nil {
return err
}
答案 2 :(得分:0)
作为github问题:link 你可以这样做
err = stream.Context().Err()
if err != nil {
break
}