1998 г
Remote Scripting - удаленное исполнение скрипта
Евгений Койнов
Введение
Начнем с простого примера: вы заполняет форму в HTML странице. Если некоторые поля заполнены неверно, то после отправки формы, сервер, скорее всего, предложит исправить неверные значения. После исправления вы повторно отправляете форму и так до тех пор, пока все данные не будут заполнены правильно.
Или предположим, что при перезагрузке страницы необходимо сохранить состояние переключателей в HTML странице или значения глобальных переменных в скрипте. Для этого приходится идти на манипуляции с HTML (например, hidden поля в форме для передачи дополнительных данных) или создавать сложный скрипт взаимодействия.
В общем случае, верным будет следующее утверждение: для обеспечения интерактивного взаимодействия с сервером необходимо часто перегружать страницу.
Как нетрудно догадаться Remote Scripting решает описанные выше проблемы. Так что же такое Remote Scripting.
Что такое RS?
Remote Scripting (RS) - это механизм, обеспечивающий вызов серверных процедур из клиентского скрипта. С помощью RS, процедуры и функции, описанные на сервере, могут вызываться из скрипта HTML страницы, исполняющегося в браузере пользователя. Вызываемые процедуры и функции будем также называть серверными методами, далее вы поймете почему. Серверные методы описываются в ASP странице и для их реализации подходит любой язык сценариев (JavaScript, VBScript). При удаленном вызове процедуры и функции исполняются на сервере с полным доступом к системным ресурсам, а результат работы возвращается в клиентский скрипт.
Теперь разработчики могут создавать интерактивные Web приложения, в которых появляется возможность исполнять серверный скрипт без обновления страницы.
C использованием RS Web приложении может проверить корректность вводимых пользователем данных в процессе заполнения формы, избегая перезагрузки.
С появлением RS, Web приложение может использовать как клиентский, так и серверный скрипт. Клиентский скрипт часто используется для управления пользовательским интерфейсом, например, динамическое изменение содержимого Web страницы или обработка действий пользователя. Клиентский скрипт выполняется локально в браузере и обеспечивает интерактивный интерфейс.
Возможности применения серверного скрипта ограничиваются только вашей фантазией. Серверный скрипт может использоваться для доступа к базе данных или выполнения звена бизнес логики в многослойных приложения. При этом серверный скрипт исполняется на сервере с полным доступом к ресурсам сервера, а из клиентского скрипта его вызов почти ничем не отличается от вызова локальных процедур и методов.
Так как при вызове серверного скрипта текущая страница не покидается, то ее состояния сохраняется, а вместе с ней и состояние переключателей и глобальных переменных.
Как RS работает
RS реализован как библиотека функций, которые вызываются из клиентского скрипта при необходимости вызова серверного метода. При вызове серверного метода, запрос выделяется в прокси процесс, который запускается асинхронно в браузере (на данный момент прокси реализован как Java апплеты). Прокси процесс посылает запрос в ASP страницу, содержащую вызываемый метод. По клиентскому запросу сервер загружает ASP страницу, и специальная процедура посылает запрос необходимому методу. Если метод возвращает значение, то оно отсылается обратно в прокси процесс, который упаковывает его как объект - call объект - содержащий результат работы метода и другую полезную информацию.
Существует два варианте вызова серверных методов:
- Синхронный
- при котором скрипт вызывает удаленную процедуру и ожидает ее завершения. Случай, когда необходим результат работы удаленной процедуры для продолжения работы скрипта.
- Асинхронный
- при котором скрипт вызывает удаленную процедуру и продолжает работу, при этом страница остается доступной для пользователя.
Компоненты необходимые для Remote Scripting
Для использования RS необходимы следующие файлы в дополнении к вашим клиентским (*.htm) и серверным (*.asp) файлам:
- RS.htm - Содержит методы которые вызываются из клиентского скрипта для инициализации RS, исполнения удаленных процедур, проверки состояние вызова и получение результатов работы.
- RS.asp - Содержит методы инициализации RS на сервере и вызова необходимых функций.
- Rsproxy.class - Содержит Java класс для апплета, который обеспечивает взаимодействие клиентской и серверной страницы.
Эти файлы работают как библиотеки, вы просто включаете необходимые файлы (Rs.htm или Rs.asp) в вашу клиентскую или серверную страницу, и вызываете необходимые серверные методы.
Все необходимые файлы должны быть доступны на сервере, по умолчанию предполагается, что эти файлы находятся в папке _ScriptLibrary.
RS и безопасность
RS обеспечивает такой же уровень безопасности как Java апплеты и IFrames. По требованиям безопасности, серверные методы не могут принимать в качестве параметров структурированные данные (объекты или массивы). К тому же, удаленные процедуры должны выполняться на том же сервере, откуда была загружена страница.
Обеспечение RS с клиентской стороны
Для обеспечения RS с клиентской стороны необходимо:
- включать файла Rs.htm в вашу клиентскую страницу;
- вызвать метод, который запускает Rsproxy апплет.
Необходимо создать пустой JavaScript блок, который ссылается на файл Rs.htm, как показано ниже:
<script language = "JavaScript" src = "../_ScriptLibrary/RS.htm">
В клиентской странице этот блок может располагаться в любом месте, но до первого удаленного вызова.
Также из клиентской страницы необходимо выполнить вызов метода RSEnableRemoteScripting(). По умолчанию этот метод предполагает, что апплет Rsproxy.class находится в папке _ScriptLibrary, если это не так необходимо указать правильный путь в качестве параметра. Этот скрипт-блок должен располагаться в пределах тела документа, но после скрипт-блока ссылающегося на Rs.htm.
<body>
<script language = "JavaScript">
RSEnableRemoteScripting("../_ScriptLibrary");
</script>
Note: Таг <APPLET> создаваемым методом RSEnableScriptong() нигде явным образом в странице не фигурирует.
Каркас клиентской страницы использующей вызов удаленных процедур выглядит примерно так:
<html>
<head>
<title>Remote Scripting Test</title>
</head>
<body>
<script language = "JavaScript" src = "../_ScriptLibrary/RS.htm">
</script>
<script language = "JavaScript">
RSEnableRemoteScripting("../_ScriptLibrary");
</script>
</body>
</html>
<р4>Обеспечение RS с серверной стороны
Для работы с RS необходимо также настроить и серверные страницы. Для этого необходимо:
- Подключить серверные библиотеки и проинициализировать их.
- Реализовать функции и процедуры, которые вы собираетесь удаленно использовать.
- Объявить эти функции и процедуры в качестве серверных методов.
По умолчанию ASP страницы, вызываемые из клиентского скрипта, не отображаются в браузере - они просто выполняются на сервере, а результат отсылается клиенту. Следовательно, нет необходимости включать HTML таги в ASP страницу.
Для подключения и инициализации серверных библиотек удаленного вызова процедур необходимо:
- Посредством SSI директивы подключить файл Rs.asp.
<!-- #INCLUDE FILE = "../_ScriptLibrary/RS.ASP" -->
- Вызвать метода RSDispatch(), который используется для поиска нужной процедуры при вызове методов со стороны клиента.
<% RSDispatch %>
Вызов этого метода необходимо сделать в самом начале скрипта.
- Объявить функции и процедуры, которые вы хотите вызывать из клиентского скрипта, как серверные методы. Это процедуры могут быть реализованы на любом языке сценариев. Процедуры могут принимать любое число параметров, но эти параметры должны быть простого типа - строки, числа. В качестве параметров не могут использоваться объекты или массивы.
Note: При вызове удаленных процедур все параметры преобразуются в строки и если вы используете другие простые типы необходимо вручную приводить их к нужному типу в вызываемой процедуре.
После создания функций и процедур необходимо объявить их серверными методами. Для этого создается объект public_description содержащий описание нужных функций и процедур. В следующем примере в качестве конструктора объекта public_description вызывается функция MyServerMethod():
<script languge = "JavaScript">
var public_description = new MyServerMethods();
В конструкторе сопоставляются имена вызываемых функций и имена серверных методов.
function constructor() {
//for JavaScript methods
this.methodName = functionName;
//for VBScript methods
this.methodName = Function('p1','p2','return functionName(p1,p2)')
}
Где:
- functionName -
имя вызываемой процедуры или функции;
- methodName -
внешнее имя серверного метода, непосредственно использующееся при вызове;
Note: Механизм объявления интерфейса посредством объекта public_description реализован только в JavaScript.
Следующий пример демонстрирует ASP страницу, в которой объявляется два серверных метода square и add:
<% RSDispatch %>
<!--#INCLUDE FILE="../_ScriptLibrary/RS.ASP"-->
<script runat = server language = "JavaScript">
var public_description = new MyServerMethods();
function MyServerMethods() {
this.square = squareNumber;
this.add = Function( 'n1','n2','return addNumbers(n1,n2)' );
}
function squareNumber(numberToSquare){
return numberToSquare * numberToSquare;
}
</script>
< script runat = server language ="VBScript">
Function addNumbers(num1, num2)
addNumbers = CInt(num1) + CInt(num2)
End Function
</script>
Вызов серверных методов
RS позволяет создать объект, который ссылается на ASP страницу, содержащую описание серверных методов. Это позволяет использовать стандартный object.method() синтаксис для вызова удаленных методов. Далее этот объект будем для простоты называть page объектом.
Чтобы сослаться на ASP страницу как на объект необходимо в клиентском скрипте вызвать метод RSGetASPObject(), передавая URL и имя ASP страницы в качестве параметра.
ASPobj = RSGetASPObject(url)
Синхронный вызов
После настройки RS вы можете вызывать серверные методы из клиентского скрипта. По умолчанию вызов серверного метода осуществляется синхронно - клиентский скрипт останавливается до окончания работы вызываемого метода и возвращения результата работы.
В качестве результата работы в клиентский скрипт возвращается объект call, который содержит результат работы и дополнительную статусную информацию. Свойство return_value объекта call содержит результат работы удаленного метода. Другие свойства объекта call позволяют получить информацию о статусе вызова удаленной процедуры.
Если вы создали page объект, то можно использовать стандартный object.method() синтаксис для вызова процедуры. Но кроме этого есть возможность вызова серверных методов без page объекта.
Для вызова серверного метода синхронно:
- Если вы создали page объект, то вызов выглядит следующим образом:
JavaScript:
callObject = ASPObject.methodName(p1, p2[,...])
VBScript:
set callObject = ASPObject.methodName(p1, p2[,...])
- Если page объект создан не был, используется RSExecute() функция и вызов выглядит так:
JavaScript:
callobject = RSExecute(url, methodName, p1, p2[,...])
VBScript:
set callobject = RSExecute(url, methodName, p1, p2[,...])
Где:
- сallObject - имя call объекта;
- ASPObject - объект ссылающийся на ASP страницу.
- url - URL ASP страницы содержащей описание серверных методов. Эта страница должна находится на том же сервере, что и страница осуществляющая вызов.
- methodName - имя метода, который вы хотите исполнить.
- p1, p2 - параметры необходимые для вызова methodName метода. Параметра передаются по значению. В качестве параметров могут быть переданы значения простых типов.
В качестве примера рассмотрим скрипт в котором при нажатии на кнопку btnAdd вызывается серверный метод Add. В качестве параметров передается содержимое полей ввода txt1 и txt2, а результат выводится в текстовом поле txt3:
<script language = "JavaScript" for = "btnAdd" event="onclick">
rsMath = RSGetASPObject("../myPages/RSMath.asp");
number1 = txt1.value;
number2 = txt2.value;
co = rsMath.Add(number1,number2);
txt3.value = "The sum is " + co.return_value;
</script>
Аналогичный вызов, но без использования page объекта:
<script language = "JavaScript" for = "btnAdd" event="onclick">
number1 = txt1.value;
number2 = txt2.value;
co = RSExecute("RSmath.asp","add",number1,number2);
txt3.value = "The sum is " + co.return_value;
</script>
Как видно из второго примера для удаленного вызова используется функция RSExecute(). В качестве параметров передается URL ASP страницы, имя серверного метода и параметры.
Асинхронный вызов
Можно вызывать удаленные методы асинхронно - клиентский скрипт продолжает работать пока серверный метод исполняется и следовательно страница остается доступной для пользователя.
Вызов серверного метода асинхронно схож с синхронным вызовом, за исключением появления дополнительных параметров при вызове:
- Ссылка на callback функцию в клиентском скрипте, которая вызывается при успешном завершении работы серверного метода.
- Ссылка на error callback функцию, которая вызывается при возникновении ошибки
- Необязательные контекстные параметры. Эти данные просто вернутся обратно по окончании работы серверного метода.
Как и при синхронном вызове, асинхронный вызов создает объект call, содержащий результат работы серверного метода и дополнительную статусную информацию.
- При асинхронном вызове объект call передается в callback функцию в качестве параметра. Следовательно, вы можете проверить статус вызова и получить результат работы метода.
Так как при асинхронном вызове необходимо передать ссылку на callback функцию, то используется только JavaScript.
Для вызова серверного метода асинхронно:
- Если вы создали page объект, то используется следующая форма вызова.
callObject = ASPObject.methodName(p1, p2[,...],
callbackFunction, errorCallbackFunction, context);
- В противном случае используется RSExecute() функция:
callobject = RSExecute(url, methodName, p1, p2[,...],
callbackFunction, errorCallbackFunction, context)
Где:
- callobject - имя call объекта;
- ASPObject - объект ссылающийся на ASP страницу;
- url - URL ASP страницы содержащей описание серверных методов. Эта страница должна находится на том же сервере, что и страница осуществляющая вызов;
- methodName - имя метода, который вы хотите исполнить;
- p1, p2 - параметры необходимые для вызова methodName метода. Параметра передаются по значению. В качестве параметров могут быть переданы значения простых типов.
- callbackFunction - ссылка на JavaScript функцию в клиентском скрипте, которая будет вызвана, когда удаленный метод окончит работу. Т. к. вы передаете ссылку, не включайте имя функции в кавычки.
- errorCallbackFunction - ссылка на необязательную JavaScript функцию в клиентском скрипте, которая будет вызвана, если при работе удаленного метода произойдет ошибка. Т. к. вы передаете ссылку, не включайте имя функции в кавычки.
- context - необязательные параметры вызова, эти данные вернутся обратно.
Например, в следующем скрипте асинхронно вызывается серверный метод square. После работы метода вызывается функция showResults(). Имя операции передается как context-параметр.
<script language = "JavaScript" for = "btnSquare" event = "onclick">
rsMath = RSGetASPObject("../myPages/RSMath.asp");
number1 = txt1.value;
context = "squaring";
co = rsMath.square(number1,showResults,context);
</script>
Аналогичный пример с использованием RSExecute метода:
<script language = "JavaScript" for = "btnSquare" event = "onclick">
number1 = txt1.value;
context = "squaring";
co = RSExecute("RSmath.asp","square",number1,showResults,context);
</script>
Функция showResults, которая является callback функций в предыдущем примере, может выглядеть следующим образом:
<script language = "JavaScript">
function showResults(co) {
typeOp = co.context;
rValue = co.return_value;
txt2.value = "Result of " + typeOp + "operation = " + rValue;
}
</script>
В данном случае callback функция служит для вывода результата работы операции. Функция демонстрирует, как вы можете использовать context свойство для определения того, какая операция арифметическая применялась.
Вы можете проверить состояние работы удаленного метода. При асинхронном вызове, можно проверить состояние работы серверного метода. Для этого используется свойства status объекта call Возможные значения свойства status:
- -1 - произошла ошибка
- 0 - работа завершена
- 1 - в процессе (только для асинхронного вызова)
Асинхронный вызов можно прервать, для этого используется cancel() метод объекта call.
Обработка ошибок
При вызове удаленных серверных методов могут происходить разного рода ошибки: синтаксические ошибки, ошибки времени исполнения, ошибки при вызове методов. RS имеет механизмы оповещения о происходящих ошибках.
Реакция на ошибки немного различается при синхронном и асинхронном вызове. Если при синхронном вызове произошла ошибка, механизм обработки ошибок выбрасывает сообщение об ошибке в окно браузера. Текстом сообщения является message свойство call объекта. Если ошибка происходит при асинхронном вызове, то вы можете ее перехватить, определяя error callback функцию.
При асинхронном вызове передаете ссылку на error callback функцию в качестве параметра. Т. к. передается указатель на функцию, то при таком вызове можно использовать только JavaScript. Примеры с использованием объекта ссылающегося на серверную страницу и без:
callObject = ASPObject.methodName(p1, p2[,...], callbackFunction,
errorCallbackFunction, context)
callobject = RSExecute(url, methodName, p1, p2[,...], callbackFunction,
errorCallbackFunction, context)
При синхронном и асинхронном вызове вы можете получать информацию о происходящих ошибках через свойства call объекта. Если вы определяете error callback функцию, то call объект передается в качестве параметра как и в случае callback функции. Полезные свойства call объекта при обработке ошибочных ситуаций:
- status
содержит -1 если при удаленном вызове произошла ошибка.
- data
содержит необработанное сообщение переданное сервером в XML формате. Это лучший источник информации при отладке, т. к. он содержит полную информацию об ошибке.
- message
содержит сообщение об ошибке созданное прокси процессом. Сообщение об ошибке в message не обязательно совпадает с содержанием свойства data. Например, если ASP страница содержит ошибку, детальная информация об ошибке содержится в data, а message только содержит сообщение о том, что при выполнение произошла ошибка.
Следующий пример демонстрирует работу error callback функции в клиентском скрипте.
<script language = "JavaScript" for = "btnSquare" event = "onclick">
rsMath = RSGetASPObject("rsadd.asp");
number1 = txt1.value;
context = "squaring";
co = rsMath.square(number1,showResults,showErrors,context);
function showErrors(co){
msg = "The raw data returned by the remote method call is "
msg = msg + co.data
alert(msg);
msg = "The following error occurred during the "
msg = msg + co.context
msg = msg + " remote scripting call:\n"
msg = msg + co.message;
alert(msg);
}
</script>
Приложение А: Свойства и методы call объекта
При вызове серверного метода возвращается не return-значение вызываемого метода, а объект, содержащий результат работы метода плюс дополнительную статусную информацию. В следующей таблицы сведены свойства и методы call объекта.
Свойство |
Описание |
Id |
Уникальный идентификатор call объекта, создается при первом вызове. |
Return_value |
return-значение вызываемого метода. |
Data |
Необработанные статусные данные в XML формате. |
Status |
Текущее состояние вызова, возможные значения:
- -1 - ошибка
- 0 - метод завершил работу
- 1 - метод не завершил работу
|
Message |
Текстовая информация о вызове. Если вызов успешный, то message содержит "Complete". Если произошла ошибка, message содержит сообщение об ошибке. |
Callback |
Имя callback функции для данного вызова. |
error_callback |
Имя error callback функции для данного вызова. |
Context |
Контекстный параметр, передается при вызове и без изменений возвращается с call объектом. |
Метод |
Описание |
Wait |
Останавливает работу клиентского скрипта до завершения работы асинхронно вызванного серверного метода. |
Cancel |
Останавливает работу асинхронно вызванного метода. |