第三十六章 使用 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
时才填充。