第三十六章 使用 CSP 进行基于标签的开发 - 使用尽可能少的#server和#call调用
#server
和#call
的工作原理是,让浏览器向页面发出HTTP
请求,其中包含一个特殊的加密令牌,该令牌告诉Caché
要运行的方法名。Caché
运行这个方法,它发回的任何输出都在浏览器上以JavaScript
的形式执行,此外,#server
调用也可以返回一个值。 因为这些调用都使用HTTP
请求,所以它们在网络数据包、服务器上的CPU
等方面的开销与普通CSP
页面请求大致相同。 如果使用大量的#server
请求,那么它将极大地降低应用程序的可伸缩性,因为每个#server
调用都要求从Caché
服务器获得一个新的CSP
页面。 这意味着,与传统的web
页面(即您访问URL
并生成一次页面)不同,一个包含10
个服务器调用的CSP页面的成本与生成10
个CSP
页面的成本相同; 如果可以减少#server
调用的数量,那么可以将应用程序支持的用户数量增加10
倍。
减少#server
调用数量的方法是确保使用的每个#server
调用都是应用程序真正需要的,如果是的话,则确保这个#server
调用在服务器上做尽可能多的工作。 例如,下面是一个JavaScript
块,它使用来自服务器的一些新值更新表单。
注意,这段代码使用CSP
关键字CSPPage
来引用页面本身,而不是Javascript
关键字self
。 在本例中,这两个关键字的作用相同。 我们建议使用CSPPage
,因为self
可以在不同的上下文中意外地起作用。
<script language="JavaScript"> function UpdateForm() { CSPPage.document.form.Name.value = #server(..workGet("Name",objid))#; CSPPage.document.form.Address.value = #server(..workGet("Address",objid))#; CSPPage.document.form.DOB.value = #server(..workGet("DOB",objid))#; } </script> 复制代码
服务器代码如下所示。 (通常它会使用一个对象或SQL
,但这里我们使用一个全局来保持代码小。)
<script language="Cache" method="workGet" arguments="type:%String,id:%String" returntype="%String"> Quit $get(^work(id,type)) </script> 复制代码
这一次更新从Caché
服务器发出三次新网页调用! 这可以转换为一个#server
调用,一次更新所有的值,JavaScript
变成:
<script language="JavaScript"> function UpdateForm() { #server(..workGet(objid))#; } </script> 复制代码
方法定义为:
<script language="Cache" method="workGet" arguments="id:%String" returntype="%String"> &js<CSPPage.document.form.Name.value = #($get(^work("Name",objid)))#; CSPPage.document.form.Address.value = #($get(^work("Address",objid)))#; CSPPage.document.form.DOB.value = #($get(^work("DOB",objid)))#;> </script> 复制代码
因此,只需传递一次数据,然后让Caché
完成所有工作,而不是多次调用。 如果你有一个更复杂的JavaScript
例子,比如:
<script language="JavaScript"> function UpdateForm() { CSPPage.document.form.Name.value = #server(..workGet("Name",objid))#; if (condition) { CSPPage.document.form.DOB.value = #server(..workGet("DOB",objid))#; } else { CSPPage.document.form.DOB.value = ''; } } </script> 复制代码
那么这应该仍然只需要一个#server
调用。 你只需要将整个if
条件嵌入到由#server
调用返回的JavaScript
中,所以代码workGet
方法最终看起来像这样:
<script language="Cache" method="workGet" arguments="id:%String" returntype="%String"> &js<CSPPage.document.form.Name.value = #(^work("Name",objid))#; if (condition) { CSPPage.document.form.DOB.value = #(^work("DOB",objid))#; } else { CSPPage.document.form.DOB.value = ''; } > </script> 复制代码
为#server
和#call
创建自定义HyperEvent
错误处理程序
如果您使用超事件(#server
或#call
)调用某个东西,并且在执行时,它由于某种原因无法与服务器通信,然后生成一个错误,那么CSP
的默认行为是在一个警告框中显示错误。 如果希望单独处理错误,比如记录它或向用户显示不同的消息,那么编写一个cspRunServerMethodError JavaScript
函数。 下面的例子像默认行为一样在警告框中显示错误:
function cspRunServerMethodError(errortext,error) { //alert('cspRunServerMethodError - cspHyperEventErrorHandler\n\nerrortext:' + errortext + '\n\nerror-object:\n' + JSON.stringify(error, null, 4) ); if (error.code == '401') { document.location.href = '#(..Link(%request.URL))#'; //reloads the page } else { //... } return null; } 复制代码
cspHyperEventError
对象类型具有以下属性和值:
code
:对应于HTTP
响应代码或来自正在使用的XMLHttpRequest
对象的响应代码。XMLHttpRequest
代码可能是特定于浏览器的。tex
t:一个空闲的文本字段,对应于返回给cspRunServerMethodError()
回调函数的当前文本。serverCode
:对应于服务器上的错误编号(如果可用)。 该值可以为空。serverText
:来自服务器的错误消息,如果可用的话。 该值默认为空字符串,即" "
。exception
异常:触发错误的异常。 该值可以为空。arguments
:捕获异常的函数的参数列表。 此值可以为空,并且仅在定义了exception
时才填充。