自己做视频类网站用哪个cms,wordpress里面主题文档怎么编辑,怎么做网站报告,2018爱情动做网站env.js#xff08;env的初始化以及服务的加载#xff09;
路径#xff1a;addons\web\static\src\env.js
这个文件的作用就是初始化env#xff0c;主要是加载所有的服务。如orm, title, dialog等。
1、env.js 的加载时机
前文我们讲过前端的启动函数#xff0c;start.…env.jsenv的初始化以及服务的加载
路径addons\web\static\src\env.js
这个文件的作用就是初始化env主要是加载所有的服务。如orm, title, dialog等。
1、env.js 的加载时机
前文我们讲过前端的启动函数start.js,其中有这么两句这里有两个函数makeEnv和startServices都在同级目录的env.js里 const env makeEnv();await startServices(env);2、 makeEnv()
export function makeEnv() {return {bus: new EventBus(),services: {},debug: odoo.debug,get isSmall() {throw new Error(UI service not initialized!);},};
}从代码可以看出env有4个属性
bus 全局数据总线services全局服务对象debug 是否debug模式isSmall判断手机端还是移动端
这里抛出一个异常是为了在后面会覆盖这个方法。
从中可以看出env最重要的其实就两个对象一个是全局数据总线负责组件之间通信另一个就是service。
3、startServices
启动所有在注册表中注册的服务并且保证所有的依赖都得到满足。
首先获取所有在注册表中注册的服务serviceRegistry
初始化元数据SERVICES_METADATA 主要是保存service中sync的内容有什么作用还不清楚
主角开始上场 startServices
启动所有在注册表中注册的服务并且保证每个服务的依赖都得到满足。 await Promise.resolve(); // 等待之前的异步操作都完成const toStart new Set(); // 初始化要启动的服务因为每个服务都不同所以用了setserviceRegistry.addEventListener // 这段没看懂这里添加了一个事件监听动态增加注册服务的await _startServices(env, toStart); // 将env和toStart对象传入干正事了
4._startServices(env, toStart)
4.1 填充 toStart 集合 const services env.services; //获取了env中的service对象这时候还是空的啥也没有// 根据注册表中的服务信息初始化了toStart集合里面都是创建好的实例对象并且有一个name属性。for (const [name, service] of serviceRegistry.getEntries()) {if (!(name in services)) {const namedService Object.assign(Object.create(service), { name });toStart.add(namedService);}}4.2、findNext()
关键的地方来了 这里有一个关键的函数findNext()先看看它的定义
// 从toStart集合中遍历有过集合中的服务有依赖并且依赖都已经满足了则返回这个service如果没有依赖那么直接返回找到第一个就返回不叨叨直到找不到返回null
function {for (const s of toStart) {if (s.dependencies) {if (s.dependencies.every((d) d in services)) {return s;}} else {return s;}}return null;}4.3 、启动服务并填充到env的services中
在start函数中findNext函数返回的服务第一步要最的就是从toStart 删除这样遍历的次数会越来越少我看过odoo17一共有69个服务while一共还要遍历69次每次加载一个服务。 通过这种方式很好的处理了服务之间的依赖关系并且最大限度的实现了并行。 // start as many services in parallel as possible 并行启动尽可能多的服务async function start() {let service null;const proms [];while ((service findNext())) {const name service.name;toStart.delete(service); // 删除要加载的服务const entries (service.dependencies || []).map((dep) [dep, services[dep]]);const dependencies Object.fromEntries(entries);let value;try {value service.start(env, dependencies); // 调用start函数,并将返回值付给value} catch (e) {value e;console.error(e);}if (async in service) {SERVICES_METADATA[name] service.async; // 保存服务的元数据后面可能会有用}if (value instanceof Promise) { // 如果value是一个Promiseproms.push(new Promise((resolve) {value.then((val) {services[name] val || null; // 将promise的返回值保存到services中}).catch((error) {services[name] error;console.error(Cant load service name because:, error);}).finally(resolve);}));} else {services[service.name] value || null; // 如果不是promise直接将value保存到services中}}await Promise.all(proms); // 等待所有的proms完成if (proms.length) {return start(); }}到这里前端js就完成了所有service的加载要注意的是 env.services中保存的不是 services对象本身而是service对象的start函数返回的对象。
这点很重要每个service都要有start函数而且要有返回值。
4.4、后面还有一段是异常处理 if (toStart.size) {const names [...toStart].map((s) s.name);const missingDeps new Set();[...toStart].forEach((s) s.dependencies.forEach((dep) {if (!(dep in services) !names.includes(dep)) {missingDeps.add(dep);}}));const depNames [...missingDeps].join(, );throw new Error(Some services could not be started: ${names}. Missing dependencies: ${depNames});}如果toStart.size 0 ,说明这里面的服务的依赖想没有得到满足所以无法加载会抛出一个Error
5、附录odoo17 env.js
/** odoo-module **/import { registry } from ./core/registry;import { EventBus } from odoo/owl;// -----------------------------------------------------------------------------
// Types
// -----------------------------------------------------------------------------/*** typedef {Object} OdooEnv* property {import(services).Services} services* property {EventBus} bus* property {string} debug* property {(str: string) string} _t* property {boolean} [isSmall]*/// -----------------------------------------------------------------------------
// makeEnv
// -----------------------------------------------------------------------------/*** Return a value Odoo Env object** returns {OdooEnv}*/
export function makeEnv() {return {bus: new EventBus(),services: {},debug: odoo.debug,get isSmall() {throw new Error(UI service not initialized!);},};
}// -----------------------------------------------------------------------------
// Service Launcher
// -----------------------------------------------------------------------------const serviceRegistry registry.category(services);export const SERVICES_METADATA {};
let startServicesPromise null;/*** Start all services registered in the service registry, while making sure* each service dependencies are properly fulfilled.** param {OdooEnv} env* returns {Promisevoid}*/
export async function startServices(env) {// Wait for all synchronous code so that if new services that depend on// one another are added to the registry, theyre all present before we// start them regardless of the order theyre added to the registry.debuggerawait Promise.resolve();const toStart new Set();serviceRegistry.addEventListener(UPDATE, async (ev) {// Wait for all synchronous code so that if new services that depend on// one another are added to the registry, theyre all present before we// start them regardless of the order theyre added to the registry.await Promise.resolve();const { operation, key: name, value: service } ev.detail;if (operation delete) {// We hardly see why it would be usefull to remove a service.// Furthermore we could encounter problems with dependencies.// Keep it simple!return;}if (toStart.size) {const namedService Object.assign(Object.create(service), { name });toStart.add(namedService);} else {await _startServices(env, toStart);}});await _startServices(env, toStart);
}async function _startServices(env, toStart) {if (startServicesPromise) {return startServicesPromise.then(() _startServices(env, toStart));}const services env.services;for (const [name, service] of serviceRegistry.getEntries()) {if (!(name in services)) {const namedService Object.assign(Object.create(service), { name });toStart.add(namedService);}}// start as many services in parallel as possibleasync function start() {let service null;const proms [];while ((service findNext())) {const name service.name;toStart.delete(service);const entries (service.dependencies || []).map((dep) [dep, services[dep]]);const dependencies Object.fromEntries(entries);let value;try {value service.start(env, dependencies);} catch (e) {value e;console.error(e);}if (async in service) {SERVICES_METADATA[name] service.async;}if (value instanceof Promise) {proms.push(new Promise((resolve) {value.then((val) {services[name] val || null;}).catch((error) {services[name] error;console.error(Cant load service name because:, error);}).finally(resolve);}));} else {services[service.name] value || null;}}await Promise.all(proms);if (proms.length) {return start();}}startServicesPromise start();await startServicesPromise;startServicesPromise null;if (toStart.size) {const names [...toStart].map((s) s.name);const missingDeps new Set();[...toStart].forEach((s) s.dependencies.forEach((dep) {if (!(dep in services) !names.includes(dep)) {missingDeps.add(dep);}}));const depNames [...missingDeps].join(, );throw new Error(Some services could not be started: ${names}. Missing dependencies: ${depNames});}function findNext() {for (const s of toStart) {if (s.dependencies) {if (s.dependencies.every((d) d in services)) {return s;}} else {return s;}}return null;}
}