Date: Thu, 28 Mar 2024 09:12:28 +0000 (UTC) Message-ID: <1215312342.24451.1711617148900@ae5f4610bf64> Subject: Exported From Confluence MIME-Version: 1.0 Content-Type: multipart/related; boundary="----=_Part_24450_109741560.1711617148899" ------=_Part_24450_109741560.1711617148899 Content-Type: text/html; charset=UTF-8 Content-Transfer-Encoding: quoted-printable Content-Location: file:///C:/exported.html
This page shows how to create an Ice client application with Jav= aScript.
On this page:
The first step in creating our JavaScript application is to compile our = Slice definition = to generate JavaScript proxies. You can compile the definition as follows:<= /p>
$ slice2js&n= bsp;Printer.ice
The slice2js
compiler produces a single source file, <=
code>Printer.js, from this definition. The exact contents of the sou=
rce file do not concern us for now =E2=80=94 it contains the generated code=
that corresponds to the Printer
interface we defined in Printer.ice
.
The client code, in Client.js
, is shown below in full:
var Ice= =3D require("ice").Ice; var Demo =3D require("./Printer").Demo; var ic; Ice.Promise.try( function() { ic =3D Ice.initialize(); var base =3D ic.stringToProxy("SimplePrinter:default -p 10000"); return Demo.PrinterPrx.checkedCast(base).then( function(printer) { return printer.printString("Hello World!"); }); } ).finally( function() { if(ic) { return ic.destroy(); } } ).exception( function(ex) { console.log(ex.toString()); process.exit(1); });
The program begins with The program begins with a call to require<=
/code> statements that assign modules from the Ice run time and the generat=
ed code to convenient local variables. (These statements=
are necessary for use with NodeJS. Browser applications would omit these s=
tatements and load the modules a different way.)=
p>
interface. To do this, we need to do a down-cast by=
calling Ice.Promise.try
to l=
aunch a chain of promises (or futures) that ha=
ndles the asynchronous nature of Ice invocations with a structure that rese=
mbles synchronous code.
try
is executed immediately. T=
he body of this function begins by calling Ice.initialize
=
to initialize the Ice run time. The call to initialize
&n=
bsp;returns an Ice.Communicator
reference, which is =
the main object in the Ice run time.stringToProxy
on the communicator, =
with the string "SimplePrinter:default -p 10000"
. Note th=
at the string contains the object identity and the port number that were us=
ed by the server. (Obviously, hard-coding object identities and port number=
s into our applications is a bad idea, but it will do for now; we will see =
more architecturally sound ways of doing this when we discuss IceGrid.)stringToProxy
is of type&n=
bsp;Ice.ObjectPrx
, which is at the root of the inheritance tre=
e for interfaces and classes. But to actually talk to our printer, we need =
a proxy for a Demo::Printer
interface, not an <=
code>ObjectDemo.PrinterPrx.checkedCast
. A checked cast send=
s a message to the server, effectively asking "is this a proxy for a <=
code>Demo::Printer interface?" If so, the call returns a proxy =
of type Demo::PrinterPrx
; otherwise, if the proxy denotes=
an interface of some other type, the call returns null
.<=
/li>
checkedCast
function involves a remote invocation=
to the server, which means this function has asynchronous semantics and th=
erefore it returns a new promise object.then
on the promise returned by checkedCast<=
/code> and supply a "success" function, meaning the code that's executed wh=
en checkedCast
succeeds. This inner function accepts one argum=
ent, printer
, representing a proxy to the newly-downcaste=
d object, or null
if the remote object doesn't support th=
e Printer
interface.
printStri=
ng
method, passing it the time-honored "Hello World!"
string. The server prints t=
hat string on its terminal. Again, printString
is a remot=
e invocation, and it returns a promise that the success function passes alo=
ng as its own return value.then
function also returns a new promise which ou=
r outer function passes back to try
. This outer promise i=
s chained to the promise associated with the printString
=
invocation; the outer promise completes successfully if and when the <=
code>printString invocation completes successfully.finally
is executed after the&=
nbsp;try
block has completed, whether or not it completes succ=
essfully. If we created a communicator in the try
block, we de=
stroy it here. Doing this is essential in order to correctly finalize the I=
ce run time: the program must call destroy on any communicator it has created; otherwise, undefined behavior=
results. The destroy
function has asynchronous sema=
ntics, so we return its promise to ensure no subsequent code is executed un=
til destroy
completes.
exception
is the defau=
lt exception handler for this entire promise chain.The server must be started before the client. Since Ice for JavaScript d= oes not currently include a complete server-side implementation, we need to= use a server from another language mapping. In this case, we will use the = C++ server:
$ serve= r
At this point, we won't see anything because the server simply waits for= a client to connect to it. We run the client in a different window:
$ node = Client.js $
The client runs and exits without producing any output; however, in the =
server window, we see the "Hello World!"
that is produced by t=
he printer. To get rid of the server, we interrupt it on the command line.<=
/p>
If anything goes wrong, the client will print an error message. For exam= ple, if we run the client without having first started the server, we get s= omething like the following:
Ice::Connect= ionRefusedException ice_cause: "Error: connect ECONNREFUSED" error: "ECONNREFUSED"
Note that, to successfully run the client, NodeJS must be able to locate= the Ice for JavaScript modules. See the Ice for JavaScript installation in= structions for more information.