最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

JS利用中介模式開發(fā)全局控制器

 更新時間:2023年09月14日 10:32:10   作者:jump__jump  
這篇文章主要為大家介紹了JS利用中介模式開發(fā)全局控制器圖文示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪

中介模式

中介模式定義了一個單獨的(中介)對象,來封裝一組對象之間的交互。將這組對象之間的交互委派給與中介對象交互,來避免對象之間的直接交互。

在實際的項目中,程序由許多對象組成,對象間的交流錯綜復(fù)雜。

隨著應(yīng)用程序的規(guī)模增大,對象越來愈多,他們之間的關(guān)系也越來復(fù)雜。對象間很容易出現(xiàn)相互引用而導(dǎo)致程序無法運行。同時開發(fā)者需要改變或者刪除某一個對象時候,需要查找并且改造所有引用到它的對象。這樣一來,改造的成本會變的非常高。

但中介者模式可以讓各個對象之間得以解耦。

之前的場景下,如果 A 發(fā)生了改變,開發(fā)者需要修改 B、D、E、F 4 個對象,而通過中介者模式,我們只需要修改中介者這一個對象即可。

中介者的好處是簡化了對象之間的交互,壞處則是中介類有可能會變成大而復(fù)雜的“上帝類”(God Class)。所以,在使用中介者模式時候,設(shè)計上一定要非??酥?。

實際使用

在前端項目開發(fā)的過程中,有很多業(yè)務(wù)無關(guān)的功能,但這些功能會散落在各個業(yè)務(wù)中,難以管理,我們利用中介者模式的思想來構(gòu)建一個的控制器。

基礎(chǔ)控制器

// axios 請求工具
import axios from "axios";
// mitt 微型發(fā)布訂閱工具
import mitt from "mitt";
const createApi = ($controller) => {
  const api = axios.create({
    baseURL: "/api",
    timeout: 10000,
  });
  api.interceptors.request.use(() => {
    // 可以通過 $controller.tmpCache 緩存一些數(shù)據(jù)
  });
  return api;
};
const createBus = () => mitt();
class Controller {
  // 臨時緩存,也可以添加更復(fù)雜的緩存
  tmpCache: Record<string, any> = {};
  // 事件總線
  bus = createBus();
  constructor() {
    this.api = createApi(this);
  }
  static instance: Controller | null = null;
  static getInstance() {
    if (!Controller.instance) {
      Controller.instance = new Controller();
    }
    return Controller.instance;
  }
}
export default Controller;

此時控制器中有一個極簡的緩存 tmpCache,發(fā)布訂閱工具。以及服務(wù)端請求方法 api。開發(fā)者只需要導(dǎo)入 Controller 類即可使用。如果后續(xù)需要更加復(fù)雜的緩存或者改造 api(如切換為 fetch)請求方法。開發(fā)者可以很快的進行替換。而無需改造對應(yīng)文件。

import axios from "redaxios";
const createApi = ($controller) => {
  const api = axios.create({
    baseURL: "/api",
  });
  const getOld = api.get;
  api.get = (...params) => {
    // 如果出發(fā)緩存直接返回
    // if (xxx) {
    //   return $controller.tmpCache
    // }
    return getOld(...params);
  };
  return api;
};

添加用戶類

登錄的用戶信息以及對應(yīng)操作可以說是對象交互的核心,將其放入控制器中。

class User {
  readonly $controller: Controller;
  user: User | null = null;
  constructor($controller: Controller) {
    this.$controller = $controller;
  }
  getData(key?: string) {
    return key ? this.user[key] : this.user;
  }
  // 登錄
  login(params) {
    $controller.api.post("/login", params).then((response) => {
      // 處理授權(quán)以及 user 信息
    });
  }
  // 退出
  logout() {
    $controller.api.post("/logout").then(() => {
      // 清理對應(yīng)數(shù)據(jù)
      $controller.tmpCache = {};
      this.user = null;
    });
  }
  // 設(shè)置用戶配置
  setSetting(params) {
    return $controller.api.post("/setting", params).then(() => {
      this.user.setting = params;
    });
  }
}
class Controller {
  constructor() {
    this.api = createApi(this);
    this.user = new User(this);
  }
  logout() {
    this.user.logout();
  }
}

此時控制器已經(jīng)具備前端開發(fā)中“大部分”功能了,如數(shù)據(jù)緩存,數(shù)據(jù)請求,登錄用戶信息處理等。大部分情況下,中介類也基本夠用了。至于其他的工具類,除非 80% 的業(yè)務(wù)都會用到,否則不建議添加到此類中去。但對于這些工具做一層簡單的封裝也是必要的(考慮后續(xù)成本)。

添加業(yè)務(wù)類

此時控制器有了用戶信息,多種緩存,請求方法等。我們可以通過注入來實現(xiàn)其他業(yè)務(wù)。

class BasicService {
  constructor($controller) {
    this.api = $controller.api;
    this.bus = $controller.bus;
  }
}
class OrderService extends BasicService {
  static xxxKey = "xxxx";
  constructor($controller) {
    super($controller);
    // 使用全局緩存
    this.cache = $controller.xxxCache;
    // 或者構(gòu)建一個新的 cache 掛載到 controller 上
    this.cache = $controller.getCreatedCache("order", XXXCache);
  }
  getOrders = async () => {
    if (this.cache.has(OrderService.xxxKey)) {
      return this.cache.get(OrderService.xxxKey);
    }
    let orders = await this.api.get("xxxxx");
    // 業(yè)務(wù)處理,包括其他的業(yè)務(wù)開發(fā)
    order = order.map();
    this.cache.set(OrderService.xxxKey, orders);
    // 可以發(fā)送全局事件
    this.bus.emit("getOrdersSuccess", orders);
    return orders;
  };
  clear() {
    // 如果構(gòu)建一個新的緩存對象,直接 clear 即可 this.cache.clear();
    this.cache.delete(OrderService.xxxKey);
  }
}
class Controller {
  // 臨時緩存,也可以添加更復(fù)雜的緩存
  tmpCache: Record<string, any> = {};
  // 事件總線
  bus = createBus();
  services: Record<string, BasicService> = {};
  getService(serviceCls) {
    // 同一個類 name 為相同的名稱
    const { name } = serviceCls;
    if (!this.services[name]) {
      this.services[name] = new serviceCls(Controller.instance);
    }
    return this.services[name];
  }
}

開發(fā)者可以在具體的代碼中這樣使用。

import Controller from "../../controller";
import OrderService from "./order-service";
// A 頁面
const orderService = Controller.getInstance().getService(OrderService);
const priceService = Controller.getInstance().getService(PriceService);
// B 頁面都會使用同一個服務(wù)
const orderService = Controller.getInstance().getService(OrderService);

有同學可能會奇怪,為什么 Controller 不能直接導(dǎo)入或者自動注入 OrderService 呢。這樣使用的原因是往往 Controller 和 BasicService 在基礎(chǔ)類中,具體的業(yè)務(wù)類分布在各個業(yè)務(wù)代碼中。

這里沒有使用任何依賴注入的框架,原因是因為如果引入了依賴注入會大大增加復(fù)雜度。同時前端的業(yè)務(wù)都是分散的,沒有必要都放在一起。在組件需要使用到服務(wù)候才將其裝載起來。

以上就是JS利用中介模式開發(fā)全局控制器的詳細內(nèi)容,更多關(guān)于JS中介模式全局控制器的資料請關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • JavaScript實現(xiàn)在標題欄上顯示當前日期的方法

    JavaScript實現(xiàn)在標題欄上顯示當前日期的方法

    這篇文章主要介紹了JavaScript實現(xiàn)在標題欄上顯示當前日期的方法,涉及javascript操作時間及DOM節(jié)點的技巧,非常具有實用價值,需要的朋友可以參考下
    2015-03-03
  • Javascript中的getter和setter初識

    Javascript中的getter和setter初識

    最近在工作中遇到了getter和setter,getter 是一種獲得屬性值的方法,setter是一種設(shè)置屬性值的方法。下面這篇文章主要給大家介紹了關(guān)于Javascript中g(shù)etter和setter的相關(guān)資料,需要的朋友可以參考借鑒,下面來一起看看吧。
    2017-08-08
  • js實現(xiàn)全選反選不選功能代碼詳解

    js實現(xiàn)全選反選不選功能代碼詳解

    這篇文章主要介紹了js實現(xiàn)全選反選不選功能,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2019-04-04
  • js的函數(shù)的按值傳遞參數(shù)(實例講解)

    js的函數(shù)的按值傳遞參數(shù)(實例講解)

    下面小編就為大家分享一篇js的函數(shù)的按值傳遞參數(shù)的實例,具有很好的參考價值,一起跟隨小編過來看看吧,希望對大家有所幫助
    2017-11-11
  • js簡單時間比較的方法

    js簡單時間比較的方法

    這篇文章主要介紹了js簡單時間比較的方法,通過2個自定義函數(shù)實現(xiàn)針對時間與日期的比較功能,涉及javascript日期及時間換算與比較操作相關(guān)技巧,需要的朋友可以參考下
    2016-08-08
  • Worker加載JS腳本跨域問題的幾種解決方法

    Worker加載JS腳本跨域問題的幾種解決方法

    Web Worker 是一種在后臺線程中運行的 JavaScript 腳本,允許我們在不阻塞主線程的情況下執(zhí)行復(fù)雜計算或處理,Worker 加載的 JS 腳本如果存在跨域問題,可能導(dǎo)致腳本無法正常加載和執(zhí)行,以下是解決 Worker 加載 JS 腳本跨域問題的幾種方法,需要的朋友可以參考下
    2025-02-02
  • Bootstrap CSS布局之代碼

    Bootstrap CSS布局之代碼

    這篇文章主要介紹了Bootstrap CSS布局之代碼的相關(guān)資料,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2016-12-12
  • JS實現(xiàn)仿蘋果底部任務(wù)欄菜單效果代碼

    JS實現(xiàn)仿蘋果底部任務(wù)欄菜單效果代碼

    這篇文章主要介紹了JS實現(xiàn)仿蘋果底部任務(wù)欄菜單效果代碼,可實現(xiàn)鼠標滑過顯示大圖標功能,涉及javascript鼠標事件及頁面元素遍歷并修改屬性的技巧,需要的朋友可以參考下
    2015-08-08
  • 原生js實現(xiàn)簡單滑動解鎖功能?js實現(xiàn)滑動拼圖解鎖

    原生js實現(xiàn)簡單滑動解鎖功能?js實現(xiàn)滑動拼圖解鎖

    這篇文章主要為大家詳細介紹了原生js實現(xiàn)簡單滑動解鎖功能,js實現(xiàn)滑動拼圖解鎖,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2022-02-02

最新評論

堆龙德庆县| 龙岩市| 轮台县| 法库县| 伊川县| 呼伦贝尔市| 海原县| 临邑县| 会理县| 察隅县| 康平县| 衡南县| 安义县| 陆良县| 利津县| 大冶市| 肥东县| 丰县| 富锦市| 绥滨县| 车险| 凤庆县| 孟村| 车致| 安义县| 岗巴县| 娱乐| 龙川县| 富源县| 安顺市| 岳普湖县| 冀州市| 封丘县| 蕲春县| 海伦市| 喀喇沁旗| 濮阳市| 沁水县| 芜湖县| 云林县| 连城县|