Client端异步Callback实现的原理

我已经介绍了Client-Callback技术,那么让我们来探讨一下Client-Callback技术怎样实现异步刷新吧(实现原理)。正所谓"知其然,知其所以然"。

运行前一篇文章的(http://blog.csdn.net/goalbell/archive/2007/09/16/1787213.aspx)例子,用firebug调试并打开查看一下WebResource.axd?d=23ERqfzqTJs6_Rg9n1je_Q2&t=633249794114687500。你会发现里面大有文章,呵呵!微软已经帮你封装好实现异步所需要的技术了,即是XmlHttpRequest对象。从firebug里面的js代码总共有537行,实现的技术大部分围绕XmlHttpRequest对象以及Dom技术。下面分析核心代码(core)的实现过程吧。Let's Start!

下面的一段代码取自WebForm_DoCallback的函数里面:

 var xmlRequest,e;
 try {
  xmlRequest = new XMLHttpRequest();
}
catch(e) {
try {
xmlRequest = new ActiveXObject("Microsoft.XMLHTTP");
 }
catch(e) {
}
}
 var setRequestHeaderMethodExists = true;
try {
 setRequestHeaderMethodExists = (xmlRequest && xmlRequest.setRequestHeader);
}
catch(e) {}
 var callback = new Object();
callback.eventCallback = eventCallback;
 callback.context = context;
 callback.errorCallback = errorCallback;
callback.async = useAsync;
 var callbackIndex = WebForm_FillFirstAvailableSlot(__pendingCallbacks, callback);
if (!useAsync) {
if (__synchronousCallBackIndex != -1) {
 __pendingCallbacks[__synchronousCallBackIndex] = null;
 }
 __synchronousCallBackIndex = callbackIndex;
 }
 if (setRequestHeaderMethodExists) {
 xmlRequest.onreadystatechange = WebForm_CallbackComplete;
 callback.xmlRequest = xmlRequest;
 xmlRequest.open("POST", theForm.action, true);
 xmlRequest.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
xmlRequest.send(postData);
return;
}

分析一下:

             首先实例化一个兼容三种浏览器(IE、FF、SF)的XmlHttpRequest对象,接着调用javascript内置的Object类来建立一个callback构造函数,该构造函数总共有四个属性。至于Callback构造函数有什么用呢?接下来这一句callback.xmlRequest=xmlRequest可以看到,将XmlHttpRequest的实例赋给了callback的属性了。最后XmlHttpRequest的实例(xmlRequest),即xmlRequest的回调方法onreadystatechange指向了WebForm_CallbackComplete,而WebForm_CallbackComplete这个函数干什么的呢?下面会分析的;xmlRequest向服务器发送请求,theForm.action怎样获得的呢?她是通过WebForm_DoPostBackWithOptions函数来获得的。由于xmlRequest是用"POST"方法向服务器请求的,所以要标明请求的头格式以及发送的参数。好了分析完上面的代码之后,我们一起来看一下WebForm_CallbackComplete究竟做了什么呢?

下面的是完整的函数示例:

function WebForm_CallbackComplete() {
 for (i = 0; i < __pendingCallbacks.length; i++) {
 callbackObject = __pendingCallbacks[i];
 if (callbackObject && callbackObject.xmlRequest && (callbackObject.xmlRequest.readyState == 4)) {
 WebForm_ExecuteCallback(callbackObject);
 if (!__pendingCallbacks[i].async) {
 __synchronousCallBackIndex = -1;
 }
 __pendingCallbacks[i] = null;
var callbackFrameID = "__CALLBACKFRAME" + i;
var xmlRequestFrame = document.getElementById(callbackFrameID);
if (xmlRequestFrame) {
 xmlRequestFrame.parentNode.removeChild(xmlRequestFrame);
 }
 }
 }

我们看一下,_pendingCallbacks怎样来的,var __pendingCallbacks = new Array();原来_pendingCallbacks是一个数组变量来的,其实从循环也可以猜到了。接着就将它赋给一个callback对象了,其实callback对象上面已经实例化了(上面那个callback构造函数)。最后就是判断xmlRequest的状态码来执行WebForm_ExecuteCallback函数。

最后,如果大家有什么好的看法可以反馈给我。

 
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
在 Java 中,可以使用 gRPC 框架实现异步的 Server-Client 回调调用。下面是一个简单的示例: 1. 定义 gRPC 服务 在.proto文件中定义服务接口和参数: ``` syntax = "proto3"; package com.example.grpc; service MyService { rpc myMethod(RequestMessage) returns (stream ResponseMessage) {} } message RequestMessage { string message = 1; } message ResponseMessage { string message = 1; } ``` 2. 生成代码 使用 protoc 工具生成 Java 代码: ``` protoc --java_out=./src/main/java/ ./src/main/proto/my_service.proto ``` 3. 实现服务接口 编写服务实现类 MyServiceImpl.java: ``` package com.example.grpc; import io.grpc.stub.StreamObserver; public class MyServiceImpl extends MyServiceGrpc.MyServiceImplBase { @Override public void myMethod(RequestMessage request, StreamObserver<ResponseMessage> responseObserver) { // 处理请求 String requestMessage = request.getMessage(); String responseMessage = "Hello, " + requestMessage + "!"; ResponseMessage response = ResponseMessage.newBuilder().setMessage(responseMessage).build(); // 发送响应 responseObserver.onNext(response); responseObserver.onCompleted(); } } ``` 4. 编写客户代码 ``` package com.example.grpc; import io.grpc.ManagedChannel; import io.grpc.ManagedChannelBuilder; import io.grpc.stub.StreamObserver; public class MyClient { public static void main(String[] args) { // 创建 channel ManagedChannel channel = ManagedChannelBuilder.forAddress("localhost", 8080).usePlaintext().build(); // 创建 stub MyServiceGrpc.MyServiceStub stub = MyServiceGrpc.newStub(channel); // 创建 request RequestMessage request = RequestMessage.newBuilder().setMessage("World").build(); // 发送请求 stub.myMethod(request, new StreamObserver<ResponseMessage>() { @Override public void onNext(ResponseMessage response) { // 处理响应 String responseMessage = response.getMessage(); System.out.println(responseMessage); } @Override public void onError(Throwable t) { // 处理异常 } @Override public void onCompleted() { // 处理完成 channel.shutdown(); } }); } } ``` 5. 运行程序 启动 gRPC 服务和客户程序,即可进行异步的 Server-Client 回调调用。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值