西西河

主题:【原创】Google Mail和XMLHTTPRequest -- 请尽量

共:💬14 🌺7 新:
全看分页树展 · 主题 跟帖
家园 减少Page Refresh确实是Web App的一个重要话题,

以前,办法似乎有这么几种:

1) Java Applet,比如Datek的那个实时显示Stock price的Streamer.

点看全图

外链图片需谨慎,可能会被源头改

2) Microsoft Remoting Script,一直没有流行起来

3)ActiveX component。本质上讲这已经出了Web app的范畴了,它需要在客户端安装binary code,比如现在很流行的Flash

最近,微软又有了一种新的技术,叫做XML-HTTP Script callbacks。本质上讲,就是client side script在背后异步调用Web server上的函数,等拿到返回结果后(全部是String),再用Client side Java script更新GUI。下面就是微软的一个小例子,Page纹丝不动,但股票价格却可以“自动”更新。这个技术比较不错,但问题是很多浏览器还不支持。

Updating Browser Displays in (Almost) Real Time

In "An Overview of the New Services, Controls, and Features in ASP.NET 2.0" in the June 2004 issue of MSDN®Magazine, I wrote about the ASP.NET 2.0 new client callback manager and demonstrated how it can be used to transmit XML-HTTP callbacks to Web servers to convert ZIP codes into city names. Dino Esposito delved more deeply into XML-HTTP callbacks in his August 2004 Cutting Edge column ("Script Callbacks in ASP.NET").

XML-HTTP callbacks enable browsers to make calls to Web servers without performing full-blown postbacks. The benefits are numerous. XML-HTTP callbacks transmit less data over the wire, thereby using bandwidth more efficiently. XML-HTTP callbacks don't cause the page to flicker because they don't cause the browser to discard the page as postbacks do. Furthermore, XML-HTTP callbacks execute less code on the server because ASP.NET short-circuits the request so that it executes the minimum amount of code necessary. Inside an XML-HTTP callback, for example, a page's Render method isn't called, significantly reducing the time required to process the request on the server.

Once they learn about the ASP.NET 2.0 client callback manager, most developers can envision lots of different uses for it. But here's an application for XML-HTTP callbacks that you might not have thought of. I regularly receive e-mail from developers asking how to create two-way connections between browser clients and Web servers. The scenario generally involves an ASP.NET Web page displaying data that's continually updated on the server. The goal is to create a coupling between the browser and the Web server so that when the data changes on the server, it's automatically updated on the client, too.

It sounds reasonable enough, but transmitting asynchronous notifications from a Web server to a browser is a nontrivial problem. However, XML-HTTP callbacks provide a handy solution. Rather than try to contrive a mechanism for letting a Web server send notifications to a browser, you can have the browser poll the server in the background using efficient XML-HTTP callbacks. Unlike META REFRESH tags, an XML-HTTP solution causes no flashing in the browser, producing a superior user experience. And unlike more elaborate methods that rely on maintaining open ports, an XML-HTTP-based solution, properly implemented, has minimal impact on scalability.

The Web page shown in Figure 1 demonstrates how dynamic page updates using XML-HTTP callbacks work. To see for yourself, launch the page called DynamicUpdate.aspx in your browser. Then open the file named Stocks.xml in the Data directory. The fictitious stock prices displayed in DynamicUpdate.aspx come from Stocks.xml. Now change one of the stock prices in Stocks.xml and save your changes. After a brief pause (two or three seconds on average), the browser's display updates to reflect the change.

点看全图

外链图片需谨慎,可能会被源头改

Figure 1 Dynamic Page Updates

What's the magic that allowed the update to occur? XML-HTTP callbacks, of course. Figure 2 lists the source code for the codebehind class that serves DynamicUpdate.aspx. Page_Load uses the new ASP.NET 2.0 Page.GetCallbackEventReference method to obtain the name of a function it can call to initiate a callback. Then it registers its own __onCallbackCompleted function, which uses client-side script to update the client's display, to be called when a callback returns. Finally, it registers a block of startup script that uses window.setInterval to call the function that initiates callbacks―the function whose name was returned by GetCallbackEventReference. Once the page loads, it polls the server every five seconds for updated data. Any changes made to the data on the server appear in the browser after a short delay.

Currently, DynamicUpdate.aspx.cs doesn't use bandwidth as efficiently as it could because every callback returns all three stock prices, even if the data hasn't changed. You could make DynamicUpdate.aspx.cs more efficient by modifying it to return only the data that has changed and to return nothing at all if no prices have changed. Then you'd have the best of both worlds: a scalable, lightweight mechanism for detecting updates on the server, and one that transmits only as much information as it must and not a single byte more. That's a win no matter how you look at it.

using System;

using System.Data;

using System.Configuration;

using System.Web;

using System.Web.Security;

using System.Web.UI;

using System.Web.UI.WebControls;

using System.Web.UI.WebControls.WebParts;

using System.Web.UI.HtmlControls;

public partial class DynamicUpdate_aspx

{

static readonly string _script1 =

"<script language=\"javascript\">\n" +

"function __onCallbackCompleted (result, context)\n" +

"{{\n" +

"var args = result.split (';');\n" +

"var gridView = document.getElementById('{0}');\n" +

"gridView.rows[1].cells[1].childNodes[0].nodeValue = args[0];\n" +

"gridView.rows[2].cells[1].childNodes[0].nodeValue = args[1];\n" +

"gridView.rows[3].cells[1].childNodes[0].nodeValue = args[2];\n" +

"}}\n" +

"</script>";

static readonly string _script2 =

"<script language=\"javascript\">\n" +

"window.setInterval (\"{0}\", 5000);\n" +

"</script>";

void Page_Load(object sender, EventArgs e)

{

// Get a callback event reference

string cbref = GetCallbackEventReference (this, "null",

"__onCallbackCompleted", "null", "null");

// Register a block of client-side script containing

// __onCallbackCompleted

RegisterClientScriptBlock ("MyScript", String.Format(

_script1, GridView1.ClientID));

// Register a block of client-side script that launches

// XML-HTTP callbacks at five-second intervals

RegisterStartupScript ("StartupScript", String.Format(

_script2, cbref));

}

// Server-side callback event handler

string ICallbackEventHandler.RaiseCallbackEvent(string arg)

{

// Read the XML file into a DataSet

DataSet ds = new DataSet ();

ds.ReadXml(Server.MapPath ("~/Data/Stocks.xml"));

// Extract the stock prices from the DataSet

string amzn = ds.Tables[0].Rows[0]["Price"].ToString ();

string intc = ds.Tables[0].Rows[1]["Price"].ToString();

string msft = ds.Tables[0].Rows[2]["Price"].ToString();

// Return a string containing all three stock prices

// (for example, "10.0;20.0;30.0")

return (amzn + ";" + intc + ";" + msft);

}

}

全看分页树展 · 主题 跟帖


有趣有益,互惠互利;开阔视野,博采众长。
虚拟的网络,真实的人。天南地北客,相逢皆朋友

Copyright © cchere 西西河