[an error occurred while processing this directive]
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.asp) в вашу клиентскую или серверную страницу, и вызываете необходимые серверные методы.

Все необходимые файлы должны быть доступны на сервере, по умолчанию предполагается, что эти файлы находятся в папке _ScriptLibrary.

RS и безопасность

RS обеспечивает такой же уровень безопасности как Java апплеты и IFrames. По требованиям безопасности, серверные методы не могут принимать в качестве параметров структурированные данные (объекты или массивы). К тому же, удаленные процедуры должны выполняться на том же сервере, откуда была загружена страница.

Обеспечение RS с клиентской стороны

Для обеспечения RS с клиентской стороны необходимо:

Необходимо создать пустой 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 страницу.

Для подключения и инициализации серверных библиотек удаленного вызова процедур необходимо:

	<!-- #INCLUDE FILE = "../_ScriptLibrary/RS.ASP" -->
	<% 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)') 
	}

Где:

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 объекта.

Для вызова серверного метода синхронно:

JavaScript:
	callObject = ASPObject.methodName(p1, p2[,...])
VBScript:
	set callObject = ASPObject.methodName(p1, p2[,...])
JavaScript:
	callobject = RSExecute(url, methodName, p1, p2[,...])
VBScript:
	set callobject = RSExecute(url, methodName, p1, p2[,...])

Где:

В качестве примера рассмотрим скрипт в котором при нажатии на кнопку 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 страницы, имя серверного метода и параметры.

Асинхронный вызов

Можно вызывать удаленные методы асинхронно - клиентский скрипт продолжает работать пока серверный метод исполняется и следовательно страница остается доступной для пользователя.

Вызов серверного метода асинхронно схож с синхронным вызовом, за исключением появления дополнительных параметров при вызове:

Как и при синхронном вызове, асинхронный вызов создает объект call, содержащий результат работы серверного метода и дополнительную статусную информацию.

Так как при асинхронном вызове необходимо передать ссылку на callback функцию, то используется только JavaScript.

Для вызова серверного метода асинхронно:

	callObject = ASPObject.methodName(p1, p2[,...], 
		callbackFunction, errorCallbackFunction, context);
	callobject = RSExecute(url, methodName, p1, p2[,...], 
		callbackFunction, errorCallbackFunction, 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:

Асинхронный вызов можно прервать, для этого используется 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 объекта при обработке ошибочных ситуаций:

Следующий пример демонстрирует работу 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 Текущее состояние вызова, возможные значения:Message Текстовая информация о вызове. Если вызов успешный, то message содержит "Complete". Если произошла ошибка, message содержит сообщение об ошибке. Callback Имя callback функции для данного вызова. error_callback Имя error callback функции для данного вызова. Context Контекстный параметр, передается при вызове и без изменений возвращается с call объектом. Wait Останавливает работу клиентского скрипта до завершения работы асинхронно вызванного серверного метода. Cancel Останавливает работу асинхронно вызванного метода.
Свойство Описание
Метод Описание

Если вы будете публиковать этот обзор, то было бы неплохо вместе с ним выставить и необходимый софт для RS.//RS10en.exe--> [an error occurred while processing this directive]