当前位置: 首页 > news >正文

网站导航设置深圳外贸网站商城

网站导航设置,深圳外贸网站商城,宣传片制作标准,做胎压的网站odoo16前端框架源码阅读——rpc_service.js 先介绍点背景知识#xff0c;这样方便阅读代码。 一、 JSONRPC的规范 https://www.jsonrpc.org/specification 中文翻译版本#xff1a;https://wiki.geekdream.com/Specification/json-rpc_2.0.html JSON-RPC是一个无状态且轻…odoo16前端框架源码阅读——rpc_service.js 先介绍点背景知识这样方便阅读代码。 一、 JSONRPC的规范 https://www.jsonrpc.org/specification 中文翻译版本https://wiki.geekdream.com/Specification/json-rpc_2.0.html JSON-RPC是一个无状态且轻量级的远程过程调用(RPC)协议。 本规范主要定义了一些数据结构及其相关的处理规则。它允许运行在基于socket,http等诸多不同消息传输环境的同一进程中。其使用JSONRFC 4627作为数据格式。 它为简单而生! 由于JSON-RPC使用JSON它具有与其相同的类型系统(见http://www.json.org或RFC 4627)。JSON可以表示四个基本类型(String、Numbers、Booleans和Null)和两个结构化类型(Objects和Arrays)。 规范中术语“Primitive”标记那4种原始类型“Structured”标记两种结构化类型。任何时候文档涉及JSON数据类型第一个字母都必须大写ObjectArrayStringNumberBooleanNull。包括True和False也要大写。 1、请求对象 发送一个请求对象至服务端代表一个rpc调用 一个请求对象包含下列成员 jsonrpc 指定JSON-RPC协议版本的字符串必须准确写为“2.0” method 包含所要调用方法名称的字符串以rpc开头的方法名用英文句号U002E or ASCII 46连接的为预留给rpc内部的方法名及扩展名且不能在其他地方使用。 params 调用方法所需要的结构化参数值该成员参数可以被省略。 id 已建立客户端的唯一标识id值必须包含一个字符串、数值或NULL空值。如果不包含该成员则被认定为是一个通知。该值一般不为NULL[1]若为数值则不应该包含小数[2]。 服务端必须回答相同的值如果包含在响应对象。 这个成员用来两个对象之间的关联上下文。 没有包含“id”成员的请求对象为通知 作为通知的请求对象表明客户端对相应的响应对象并不感兴趣 const data {id: rpcId,jsonrpc: 2.0,method: call,params: params,};2、响应对象 当发起一个rpc调用时除通知之外服务端都必须回复响应。响应表示为一个JSON对象使用以下成员 jsonrpc 指定JSON-RPC协议版本的字符串必须准确写为“2.0” result 该成员在成功时必须包含。 当调用方法引起错误时必须不包含该成员。 服务端中的被调用方法决定了该成员的值。 error 该成员在失败是必须包含。 当没有引起错误的时必须不包含该成员。 该成员参数值必须为5.1中定义的对象。 id 该成员必须包含。 该成员值必须于请求对象中的id成员值一致。 若在检查请求对象id时错误例如参数错误或无效请求则该值必须为空值。 响应对象必须包含result或error成员但两个成员必须不能同时包含。 3、错误对象 当一个rpc调用遇到错误时返回的响应对象必须包含错误成员参数并且为带有下列成员参数的对象 code 使用数值表示该异常的错误类型。 必须为整数。 message 对该错误的简单描述字符串。 该描述应尽量限定在简短的一句话。 data 包含关于错误附加信息的基本类型或结构化类型。该成员可忽略。 该成员值由服务端定义例如详细的错误信息嵌套的错误等。 code message meaning -32700 Parse error语法解析错误 服务端接收到无效的json。该错误发送于服务器尝试解析json文本 -32600 Invalid Request无效请求 发送的json不是一个有效的请求对象。 -32601 Method not found找不到方法 该方法不存在或无效 -32602 Invalid params无效的参数 无效的方法参数。 -32603 Internal error内部错误 JSON-RPC内部错误。 -32000 to -32099 Server error服务端错误 预留用于自定义的服务器错误。二、rpc_service.js 路径addons\web\static\src\core\network\rpc_service.js 1、引入相关模块 新建了相关的Error类 导入了两个js模块 browser估计是跟浏览器相关 registry 是前端的注册表 然后是定义了四个Error继承自己标准类Error RPCErrorConnectionLostErrorConnectionAbortedErrorHTTPError /** odoo-module **/import { browser } from ../browser/browser; import { registry } from ../registry;// ----------------------------------------------------------------------------- // Errors // ----------------------------------------------------------------------------- export class RPCError extends Error {constructor() {super(...arguments);this.name RPC_ERROR;this.type server;this.code null;this.data null;this.exceptionName null;this.subType null;} }export class ConnectionLostError extends Error {}export class ConnectionAbortedError extends Error {}export class HTTPError extends Error {} 2、Error对象 根据响应值来返回一个RPCError这句结构赋值挺有意思 const { code, data: errorData, message, type: subType } reponse;我猜是吧reponse中的4个属性 codedatamessagetype 分别赋值给了codeerrorDatamessagesubType有两个变量名称做了替换。有啥必要吗 // ----------------------------------------------------------------------------- // Main RPC method // ----------------------------------------------------------------------------- export function makeErrorFromResponse(reponse) {// Odoo returns error like this, in a error field instead of properly// using http error codes...const error new RPCError();error.exceptionName errorData.name;error.subType subType;error.data errorData;error.message message;error.code code;return error; } 3、定义相关变量 5个输入参数 env 前端环境似乎在前端js代码中直接可以使用这个对象。rpcId id 为了跟响应对应起来所以需要这个idurl 地址params 参数值setting 默认是一个空对象 export function jsonrpc(env, rpcId, url, params, settings {}) {const bus env.bus;const XHR browser.XMLHttpRequest;const data {id: rpcId,jsonrpc: 2.0,method: call,params: params,};const request settings.xhr || new XHR();let rejectFn;参数看着有点多其实在后面封装成service的时候 前两个参数是不用传的只需要传递后面三个就行 其实params和setting都可以不用传必须要传的只有url。 bus 总线 这里要通过总线发送一些信号rpc毕竟是远程调用难免有意外情况发生所以需要bus进行通信。 XHR: 浏览器发起request请求 data 标准的jsonrpc数据格式 rejectFn 这里值得一提在这里声明这个变量但是并没有赋值是为了后面使用。 4、复习promise promise是ES6引入的异步编程的新解决方案语法上Promise是一个构造函数用来封装异步操作并可以获取成功或失败的结果。 // new Promise 生成一个异步任务参数是具体执行任务的函数接收两个参数 // 一般叫resolve和reject都是函数异步任务执行成功调用前者否则调用后者 // 这两个方法将改变p对象的状态同时给下一步处理传递数据 // 然后调用p.then ,接收两个函数型参数分别对应异步任务成功的回调和失败的回调 const p new Promise(function(resolve,reject){setTimeout(function () {// let data数据库中的用户数据;// resolve(data);let err数据读取失败;reject(err);},1000); })p.then(function(value){console.log(value); },function(reason){console.error(reason); })// 其实promise解决的也是回调地狱嵌套过多的问题将异步任务封装成对象了 其实promise分了两步来完成对象本身只是执行了一个异步任务并没有处理异步返回的结果。 异步任务返回的结果是在p.then函数中处理的。 异步任务的返回值会影响promise对象本身的状态会决定p.then中执行哪个回调函数。 另外就是promise可以链式调用执行串行的异步任务。 5、promise 中的Bus 在promise里面往总线里发送了很多消息 if (!settings.silent) {bus.trigger(RPC:REQUEST, data.id);}这里既然发了那么就一定有地方接收在odoo中搜索一下RPC:REQUEST addons\web\static\src\webclient\loading_indicator\loading_indicator.js 这个文件代码不长直接贴过来好了。注释中大概的意思是 加载指示器 当用户执行一个动作最好是给他一些反馈说明当前有些事情正在发生。 这个指示器的作用就是在屏幕的右下角显示一个小的矩形框里面有Loading字样并且还有rpc的id。 3秒之后如果rpc依然没有完成我们将阻塞整个UI。 回头测试一下。 /** odoo-module **/import { browser } from web/core/browser/browser; import { registry } from web/core/registry; import { useService } from web/core/utils/hooks; import { Transition } from web/core/transition;import { Component, onWillDestroy, useState } from odoo/owl;/*** Loading Indicator** When the user performs an action, it is good to give him some feedback that* something is currently happening. The purpose of the Loading Indicator is to* display a small rectangle on the bottom right of the screen with just the* text Loading and the number of currently running rpcs.** After a delay of 3s, if a rpc is still not completed, we also block the UI.*/ export class LoadingIndicator extends Component {setup() {this.uiService useService(ui);this.state useState({count: 0,show: false,});this.rpcIds new Set();this.shouldUnblock false;this.startShowTimer null;this.blockUITimer null;this.env.bus.addEventListener(RPC:REQUEST, this.requestCall.bind(this));this.env.bus.addEventListener(RPC:RESPONSE, this.responseCall.bind(this));onWillDestroy(() {this.env.bus.removeEventListener(RPC:REQUEST, this.requestCall.bind(this));this.env.bus.removeEventListener(RPC:RESPONSE, this.responseCall.bind(this));});}requestCall({ detail: rpcId }) {if (this.state.count 0) {browser.clearTimeout(this.startShowTimer);this.startShowTimer browser.setTimeout(() {if (this.state.count) {this.state.show true;this.blockUITimer browser.setTimeout(() {this.shouldUnblock true;this.uiService.block();}, 3000);}}, 250);}this.rpcIds.add(rpcId);this.state.count;}responseCall({ detail: rpcId }) {this.rpcIds.delete(rpcId);this.state.count this.rpcIds.size;if (this.state.count 0) {browser.clearTimeout(this.startShowTimer);browser.clearTimeout(this.blockUITimer);this.state.show false;if (this.shouldUnblock) {this.uiService.unblock();this.shouldUnblock false;}}} }LoadingIndicator.template web.LoadingIndicator; LoadingIndicator.components { Transition };registry.category(main_components).add(LoadingIndicator, {Component: LoadingIndicator, }); 6、request 绑定load事件 request绑定了一个load事件也就是请求返回的时候触发的操作 request.addEventListener(load, () {if (request.status 502) {// If Odoo is behind another server (eg.: nginx)if (!settings.silent) {bus.trigger(RPC:RESPONSE, data.id);}reject(new ConnectionLostError());return;}let params;try {params JSON.parse(request.response);} catch (_) {// the response isnt json parsable, which probably means that the rpc request could// not be handled by the server, e.g. PoolError(The Connection Pool Is Full)if (!settings.silent) {bus.trigger(RPC:RESPONSE, data.id);}return reject(new ConnectionLostError());const { error: responseError, result: responseResult } params;if (!settings.silent) {bus.trigger(RPC:RESPONSE, data.id);}if (!responseError) {return resolve(responseResult);}const error makeErrorFromResponse(responseError);reject(error);});6.1、status 502 是个什么鬼 502 Bad Gateway错误是指代理或网关从上一个服务器接收到的响应无效或不完整。通常这种情况发生在文件太大或处理速度太慢的高流量网站上。例如当您访问一个具有高流量的网站时您的请求将被发送到它的代理服务器。如果代理服务器在尝试访问网站时无法从上游服务器获取完整的响应则会生成502错误代码。 502错误代码通常是由代理服务器、网关或负载均衡器等设备导致的而不是由您的计算机或网络连接引起的。这意味着您只能为自己的网络连接做些有限的调整但无法修复网关响应错误。 注释中也写的明白502可能是因为使用了nginx反向代理而 502错误是nginx和odoo通讯不佳造成的这种情况rpc执行失败 执行这一句 reject(new ConnectionLostError());6.2 解析返回值 如果返回的不是json格式的数据也会触发错误 try {params JSON.parse(request.response);} catch (_) {return reject(new ConnectionLostError());}catch 后面的这个下划线是什么鬼 可能是并不关心发生了什么错误只要解析错误就调用reject 6.3 解构赋值 const { error: responseError, result: responseResult } params;根据jsonrpc规范 error和result 必须并且只能返回一个。 后面也做了判断 if (!responseError) {return resolve(responseResult);}如果没有错误那就调用resolve并返回。否则说明有错误发生先生成一个error然后调用reject const error makeErrorFromResponse(responseError);reject(error);7、request绑定 error事件 request.addEventListener(error, () {if (!settings.silent) {bus.trigger(RPC:RESPONSE, data.id);}reject(new ConnectionLostError());});8、 该干正事了 request.open(POST, url);request.setRequestHeader(Content-Type, application/json);request.send(JSON.stringify(data));三行代码 1、用post方法请求的url为什么不用get? 因为post更安全 2、指定了Content-Type为json 这个很重要如果不指定服务器端不知道怎么解析数据 3、将data转成字符串并发送出去。忙活半天就是为了这句 9、定义了promise.abort Promise只有三种状态pending、resolve、reject,一个异步的承诺一旦发出经历等待pending后最终只能为成功或者失败中途无法取消abort。 这里定义promise.abort注释也讲的明白允许用户取消被忽略的rpc请求来接触对UI的阻塞并且不要显示错误。 /*** param {Boolean} rejectError Returns an error if true. Allows you to cancel* ignored rpcs in order to unblock the ui and not display an error.*/promise.abort function (rejectError true) {if (request.abort) {request.abort();}if (!settings.silent) {bus.trigger(RPC:RESPONSE, data.id);}if (rejectError) {rejectFn(new ConnectionAbortedError(XmlHttpRequestError abort));}};10、jsonrpc 这个函数就干了一件事定义了一个promise对象来发送rpc请求并把它返回。 export function jsonrpc(env, rpcId, url, params, settings {}) {const bus env.bus;const XHR browser.XMLHttpRequest;const data {id: rpcId,jsonrpc: 2.0,method: call,params: params,};const request settings.xhr || new XHR();let rejectFn;const promise new Promise((resolve, reject) {rejectFn reject;// handle successrequest.addEventListener(load, () {});// handle failurerequest.addEventListener(error, () {});request.open(POST, url);request.setRequestHeader(Content-Type, application/json);request.send(JSON.stringify(data));});promise.abort function (rejectError true) {};return promise; }11、定义RPC服务 这里对jsonrpc做了进一步封装并且注册为服务看来每个服务都有个start函数而且将env作为参数传进去。 // ----------------------------------------------------------------------------- // RPC service // ----------------------------------------------------------------------------- export const rpcService {async: true,start(env) {let rpcId 0;return function rpc(route, params {}, settings) {return jsonrpc(env, rpcId, route, params, settings);};}, };registry.category(services).add(rpc, rpcService);附录 odoo16 rpc_service.js /** odoo-module **/import { browser } from ../browser/browser; import { registry } from ../registry;// ----------------------------------------------------------------------------- // Errors // ----------------------------------------------------------------------------- export class RPCError extends Error {constructor() {super(...arguments);this.name RPC_ERROR;this.type server;this.code null;this.data null;this.exceptionName null;this.subType null;} }export class ConnectionLostError extends Error {}export class ConnectionAbortedError extends Error {}export class HTTPError extends Error {}// ----------------------------------------------------------------------------- // Main RPC method // ----------------------------------------------------------------------------- export function makeErrorFromResponse(reponse) {// Odoo returns error like this, in a error field instead of properly// using http error codes...const { code, data: errorData, message, type: subType } reponse;const error new RPCError();error.exceptionName errorData.name;error.subType subType;error.data errorData;error.message message;error.code code;return error; }export function jsonrpc(env, rpcId, url, params, settings {}) {const bus env.bus;const XHR browser.XMLHttpRequest;const data {id: rpcId,jsonrpc: 2.0,method: call,params: params,};const request settings.xhr || new XHR();let rejectFn;const promise new Promise((resolve, reject) {rejectFn reject;if (!settings.silent) {bus.trigger(RPC:REQUEST, data.id);}// handle successrequest.addEventListener(load, () {if (request.status 502) {// If Odoo is behind another server (eg.: nginx)if (!settings.silent) {bus.trigger(RPC:RESPONSE, data.id);}reject(new ConnectionLostError());return;}let params;try {params JSON.parse(request.response);} catch (_) {// the response isnt json parsable, which probably means that the rpc request could// not be handled by the server, e.g. PoolError(The Connection Pool Is Full)if (!settings.silent) {bus.trigger(RPC:RESPONSE, data.id);}return reject(new ConnectionLostError());}const { error: responseError, result: responseResult } params;if (!settings.silent) {bus.trigger(RPC:RESPONSE, data.id);}if (!responseError) {return resolve(responseResult);}const error makeErrorFromResponse(responseError);reject(error);});// handle failurerequest.addEventListener(error, () {if (!settings.silent) {bus.trigger(RPC:RESPONSE, data.id);}reject(new ConnectionLostError());});// configure and send requestrequest.open(POST, url);request.setRequestHeader(Content-Type, application/json);request.send(JSON.stringify(data));});/*** param {Boolean} rejectError Returns an error if true. Allows you to cancel* ignored rpcs in order to unblock the ui and not display an error.*/promise.abort function (rejectError true) {if (request.abort) {request.abort();}if (!settings.silent) {bus.trigger(RPC:RESPONSE, data.id);}if (rejectError) {rejectFn(new ConnectionAbortedError(XmlHttpRequestError abort));}};return promise; }// ----------------------------------------------------------------------------- // RPC service // ----------------------------------------------------------------------------- export const rpcService {async: true,start(env) {let rpcId 0;return function rpc(route, params {}, settings) {return jsonrpc(env, rpcId, route, params, settings);};}, };registry.category(services).add(rpc, rpcService);
http://www.dnsts.com.cn/news/253755.html

相关文章:

  • 济南网站建设 找小七网站域名实名认证查询
  • 网站 快照 更新慢行业门户网站大全
  • 国外音乐网站设计工作室装修网站源码
  • 江西网站做的好的企业文化wordpress浮动导航菜单
  • vue做网站前端威海网站推广
  • 阿里建站官网阿里云域名服务
  • 广州 餐饮 网站建设直播间搭建
  • 更改网站的布局公司业务管理系统
  • 金融互助平台网站制作网站备案号含义
  • 适合做网站的图片网站开发前端和后端的区别
  • 手机怎么制作钓鱼网站dedecms5.7化妆品公司网站源码
  • 为什么做游戏网站被封深圳龙岗区网站建设
  • 网站都要备案吗ui设计网课
  • 网站建设 三乐产品单页设计模板
  • 在线做venn图网站十堰北京网站建设
  • 网站开发实验总结网站首页设置伪静态
  • 菏泽做网站优化的潮州 做网站 有钱
  • 无锡网站建设企业wordpress中文竖排
  • 美妆网站设计简单做动画的网站
  • 批量优化网站软件wordpress 菜单路径
  • 企业网站管理系统 才能湖南岚鸿网站如何优化一个关键词
  • 自建站 外贸职业能力建设网网站
  • 3d渲染网站建设私募基金网站开发流程图
  • 深圳住房和建设局网站融悦居永安网站建设
  • 做淘宝客网站好搭建吗如何用flash做网站
  • 网站服务器租用和托管威海高区建设局官方网站
  • 营销网站的主题 定位 修改建议厦门海沧区建设局网站
  • 网站优化图片宿州网站建设零聚思放心
  • 网站后台管理系统如何安装微网站和微信公共平台的区别
  • 网站设计配色怎么做wordpress怎么添加登陆