Silverlight中通过Javascript的XmlHttp调用服务器端内容的同步与异步问题

Silverlight中通过Javascript的XmlHttp调用服务器端内容的同步与异步问题,第1张

概述  在做Silverlight开发时,经常需要以调用WebService的形式与服务器端进行交互。例如在Silverlight嵌入到SharePoint的项目中,常需要Silverlight调用SharePoint的WebService来与SharePoint交换信息。如果直接在Silverlight中通过C#的webclient访问WebService将涉及权限问题,需要将'clientacce

  在做Silverlight开发时,经常需要以调用WebService的形式与服务器端进行交互。例如在Silverlight嵌入到SharePoint的项目中,常需要Silverlight调用SharePoint的WebService来与SharePoint交换信息。如果直接在Silverlight中通过C#的webclIEnt访问WebService将涉及权限问题,需要将'clIEntaccesspolicy.xml'部署到服务器上对应的位置(参考《 Silverlight 2beta2 调用 SharePoint的WebService......》),所以一般采用JavaScript的方式用xmlhttp向服务器发送请求。

  JavaScript的Xmlhttp发送请求时有两种方式:同步发送和异步发送。如果采用同步发送的方式,xmlhttp.send会阻塞整个线程,导致包括Silverlight在内的页面处于停滞等待状态,直到xmlhttp得到服务器端的反馈。而采用异步发送的方式,则可避免线程被阻塞。

  这里我们用一个简单的例子来说明这个问题(示例在Silverlight 2.0 RTM环境下调试通过,源代码可在这里下载)。

  在Silverlight的Page.xmal页面上放置两个按钮分别同步和异步获取服务器端ServerSimulationPage.aspx页面的内容。为模拟实际环境,在ServerSimulationPage.aspx页面加载时调用了一个sleep函数延时3秒,并且返回的页面内容包含了瞬时时间以便查看页面内容是否更新过。我们期望在用户点击按钮时就显示一个提示用户等待的信息,直到成功得到服务器端的页面内容后再关闭提示用户等待的信息。

  当点“Get Page Content from Server(Sync Mode)”按钮时,Silverlight调用JavaScript函数getPageContentSync:

 

C#语言: 同步方式按钮的Click事件 // 同步方式获取
private voID btnGetPageContentSync_Click( object sender,RoutedEventArgs e)
{
     OpenTipInfo();

     // 调用JavaScript 以便利用Xmlhttp 同步获取服务器端数据
     object objReturn = HTMLPage.Window.Invoke( "getPageContentSync","ServerSimulationPage.aspx");
     if (objReturn != null)
         GetPageContentSuccess(objReturn.ToString());
}

 

JavaScript语言: Javascript同步方式获取服务器内容的代码 // 以“同步”方式从服务器获取页面内容
        function getPageContentSync(url) {
            var xmlhttp = getXmlhttp();
            if (xmlhttp) {
                xmlhttp.open( "GET",url,false);     //false表示同步调用,会阻塞进程,导致页面等待,即提示信息不及时显示出来
                xmlhttp.send();
                return xmlhttp.responseText;         //同步调用,可以返回结果。这里最好要判断一下返回的状态 xmlhttp.status
            }
        }

 

  由于xmlhttp.open的最后一个参数是false,表示xmlhttp以同步的方式向服务器发送请求。当xmlhttp.send()运行后,线程就在此等待,直到服务器端运行完毕并返回结果给xmlhttp,然后再将xmlhttp.responseText的内容返回给Silverlight。这个过程中虽然在Silverlight中运行“  object objReturn = HTMLPage.Window.Invoke("getPageContentSync","ServerSimulationPage.aspx"); ” 之前已经OpenTipInfo() 了,但由于线程被xmlhttp.send阻塞,所以整个过程用户感觉在获取到ServerSimulationPage.aspx页面内容之前Silverlight页面一直停滞在那里,并且似乎看不到任何提示用户等待的信息。

 

  但如果采用异步方式则能解决这一问题。当点击按钮“Get Page Content from Server(Async Mode)”时,响应Silverlight事件:

 

C#语言: 异步方式按钮的Click事件 // 异步方式获取
        private voID btnGetPageContentAsync_Click( object sender,RoutedEventArgs e)
        {
            OpenTipInfo();

            // 调用JavaScript 以便利用Xmlhttp 异步获取服务器端数据
            HTMLPage.Window.Invoke( "getPageContentAsync","ServerSimulationPage.aspx");
        }

 

  该事件中,首先OpenTipInfo()显示提示用户等待信息,然后调用JavaScript函数getPageContentAsync,但在运行“HTMLPage.Window.Invoke("getPageContentAsync","ServerSimulationPage.aspx");”时并不期待其立即返回结果。在JavaScript的getPageContentAsync函数里异步方式获取服务器端页面内容:

 

JavaScript语言: Javascript异步方式获取服务器内容的代码 // 以“异步”方式获取服务器端页面内容
        function getPageContentAsync(url) {
            var xmlhttp = getXmlhttp();
            if (xmlhttp) {
                xmlhttp.onreadystatechange = function() { doStateChange.apply(xmlhttp) }    //当返回状态改变时,通知函数doStateChange
                xmlhttp.open( "GET",true);     //true表示异步调用,false表示同步调用。如果为false,则会阻塞进程,导致页面等待,即提示信息不及时显示出来
                xmlhttp.send();
            }
        }

        // 当Xmlhttp的返回状态改变时,进行相应处理
        function doStateChange()
        {
            if ( this.readyState == 4)
            {
                if ( this.status == 200)     //调用成功,正确获得了返回信息
                {
                    var ctl = document.getElementByID( "silverlightControl");
                    if (ctl)
                        ctl.content.Page.GetPageContentSuccess( this.responseText);
                }
                else                        //调用失败,未返回正确的页面信息
                {                   
                    var ctl = document.getElementByID( "silverlightControl");
                    if (ctl)
                        ctl.content.Page.GetPageContentFailed();
                }
            }
        }

 

  这里函数getPageContentAsync中同样利用xmlhttp向服务器发送请求,但是以异步的方式发送请求“xmlhttp.open("GET",true);  ”,并且xmlhttp.send()后并不期望马上得到返回结果,所以getPageContentAsync函数没有返回任何值。但在我们监听了xmlhttp.onreadystatechange事件:

                        xmlhttp.onreadystatechange = function() { doStateChange.apply(xmlhttp) } 

  当xmlhttp接收到服务器端的反馈时就立即通知doStateChange函数,在doStateChange函数里我们可以判断是否服务器端已经运行完毕并返回了正确结果。当得知已经成功获取服务器端的页面内容后,就立即调用Silverlight里的相应事件,通知Silverlight做相应处理;如果得知获取服务器端内容失败,也要立即通知Silverlight做相应处理。

  这里涉及到JavaScript调用Silverlight的函数的问题,所以在Silverlight里必须暴露出相应的函数供JavaScript调用:

 

C#语言: Silverlight暴露函数给Javascript调用 // 获取页面内容成功 此方法暴露给JavaScript调用
        [ScriptableMember]
        public voID GetPageContentSuccess( string pageContent)
        {
            txtContent.Text = pageContent;
            CloseTipInfo();
            HTMLPage.Window.Alert( "Get page content successfully!");
        }

        // 获取页面内容失败 此方法暴露给JavaScript调用
        [ScriptableMember]
        public voID GetPageContentFailed()
        {
            CloseTipInfo();
            HTMLPage.Window.Alert( "SORRY! Get page content Failed!");
        }

  当然,xmlhttp调用其它的WebService也是类似原理。

@H_762_502@ 总结

以上是内存溢出为你收集整理的Silverlight中通过Javascript的XmlHttp调用服务器端内容的同步与异步问题全部内容,希望文章能够帮你解决Silverlight中通过Javascript的XmlHttp调用服务器端内容的同步与异步问题所遇到的程序开发问题。

如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/web/1052975.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-05-25
下一篇 2022-05-25

发表评论

登录后才能评论

评论列表(0条)

保存