117 lines
3.6 KiB
ReStructuredText
117 lines
3.6 KiB
ReStructuredText
|
|
RPC service
|
|
===========
|
|
|
|
.. list-table::
|
|
:header-rows: 1
|
|
|
|
* - Technical name
|
|
- Dependencies
|
|
* - ``rpc``
|
|
- ``notifications``
|
|
|
|
|
|
Overview
|
|
--------
|
|
|
|
The RPC service has a single purpose: send requests to the server. Its external
|
|
API is a single function, with the following type:
|
|
|
|
.. code-block:: ts
|
|
|
|
type RPC = (route: string, params?: { [key: string]: any }) => Promise<any>;
|
|
|
|
This makes it easy to use. For example, calling a controller ``/some/route`` can
|
|
be done with the following code:
|
|
|
|
.. code-block:: ts
|
|
|
|
class MyComponent extends Component {
|
|
rpc = useService("rpc");
|
|
|
|
async someMethod() {
|
|
const result = await this.rpc("/some/route");
|
|
}
|
|
}
|
|
|
|
Note that the ``rpc`` service is considered a low-level service. It should only be
|
|
used to interact with Odoo controllers. To work with models (which is by far the
|
|
most important usecase), one should use the `\ ``model`` <model.md>`_ service instead.
|
|
|
|
Calling a controller
|
|
--------------------
|
|
|
|
As explained in the overview, calling a controller is very simple. The route
|
|
should be the first argument, and optionally, a ``params`` object can be given as
|
|
a second argument.
|
|
|
|
.. code-block:: ts
|
|
|
|
const result = await this.rpc("/my/route", { some: "value" });
|
|
|
|
Technical notes
|
|
---------------
|
|
|
|
|
|
* The ``rpc`` service communicates with the server by using a ``XMLHTTPRequest`` object,
|
|
configured to work with ``application/json`` content type.
|
|
* So clearly the content of the request should be JSON serializable.
|
|
* Each request done by this service uses the ``POST`` http method
|
|
* Server errors actually return the response with an http code 200. But the ``rpc``
|
|
service will treat them as error (see below)
|
|
|
|
Error Handling
|
|
--------------
|
|
|
|
An rpc can fail for two main reasons:
|
|
|
|
|
|
* either the odoo server returns an error (so, we call this a ``server`` error).
|
|
In that case the http request will return with am http code 200 BUT with a
|
|
response object containing an ``error`` key.
|
|
* or there is some other kind of network error
|
|
|
|
When a rpc fails, then:
|
|
|
|
|
|
* the promise representing the rpc is rejected, so the calling code will crash,
|
|
unless it handles the situation
|
|
*
|
|
an event ``RPC_ERROR`` is triggered on the main application bus. The event payload
|
|
contains a description of the cause of the error:
|
|
|
|
If it is a server error (the server code threw an exception). In that case
|
|
the event payload will be an object with the following keys:
|
|
|
|
|
|
* ``type = 'server'``
|
|
* ``message(string)``
|
|
*
|
|
``code(number)``
|
|
|
|
*
|
|
``name(string)`` (optional, used by the crash manager to look for an appropriate
|
|
dialog to use when handling the error)
|
|
|
|
* ``subType(string)`` (optional, often used to determine the dialog title)
|
|
* ``data(object)`` (optional object that can contain various keys among which
|
|
``debug`` : the main debug information, with the call stack)
|
|
|
|
If it is a network error, then the error description is simply an object
|
|
``{type: 'network'}``.
|
|
When a network error occurs, a notification is displayed and the server is regularly
|
|
contacted until it responds. The notification is closed as soon as the server responds.
|
|
|
|
Specialized behaviour for components
|
|
------------------------------------
|
|
|
|
The ``rpc`` service has a specific optimization to make using it with component safer. It
|
|
does two things:
|
|
|
|
|
|
* if a component is destroyed at the moment an rpc is initiated, an error will
|
|
be thrown. This is considered an error, a destroyed component should be inert.
|
|
* if a component is destroyed when a rpc is completed, which is a normal situation
|
|
in an application, then the promise is simply left pending, to prevent any
|
|
followup code to execute.
|