> 웹 프론트엔드 > JS 튜토리얼 > 대규모 JavaScript 애플리케이션 아키텍처 디자인 패턴(고급)

대규모 JavaScript 애플리케이션 아키텍처 디자인 패턴(고급)

亚连
풀어 주다: 2018-05-21 09:23:51
원래의
2657명이 탐색했습니다.

다음은 관심 있는 학생들을 위해 제가 정리한 대규모 JavaScript 애플리케이션 아키텍처 디자인 패턴입니다.

다음은 이 기사의 주요 장입니다:

1. "JavaScript 대형 프로그램"이란 무엇입니까?

2. 현재 프로그램 아키텍처를 고려하세요

4. 브레인스토밍

5. 제안된 아키텍처

5.1.1 모듈 이론

1 요약 5.1.1.2 모듈 모드

                                                                               5.1.

5.2 아키텍처에 적용

5.2.1 외관 - 핵심 추상화

5.2.2 중재자 - 프로그램의 핵심

5.2.3 긴밀하게 협력하기

6. /subscribe 하위 확장자: 자동 등록 이벤트

7. Q & A

8. 감사 인사

"JavaScript 대형 프로그램"이란?

시작하기 전에 대규모 JavaScript 사이트가 무엇인지 정의해 보겠습니다. 많은 경험이 있는 JS 개발 전문가들도 어떤 사람들은 10만 줄 이상의 JavaScript 코드가 큰 것으로 간주된다고 말합니다. 실제로는 설치된 코드의 양으로 측정할 수 없기 때문에 크기가 1MB를 초과하는 경우에만 계산됩니다.

"큰"에 대한 나의 정의는 다음과 같습니다. 비록 정확하지는 않더라도 비교적 비슷해야 합니다.

저는 개인적으로 대규모 JavaScript 프로그램이 매우 중요하고 많은 뛰어난 개발자의 노력을 통합해야 한다고 생각합니다. 헤비급 데이터를 처리하여 브라우저에 표시하는 프로그램입니다.

현재 프로그램 아키텍처 검토

이 질문이 얼마나 중요한지는 아무리 강조해도 지나치지 않습니다. 숙련된 많은 개발자는 종종 다음과 같이 말합니다. 조금 더 큰 프로그램에서 다시 사용해도 문제 없겠죠? "특정 프로그램에서는 그렇겠지만, 큰 프로그램이다 보니 대개 분해해서 주의해야 할 부분이 크다는 점을 잊지 마세요." , 오랫동안 실행되어 온 프로그램 아키텍처를 검토하는 데 시간이 걸린다는 점을 간략하게 설명합니다. 대부분의 경우 현재 JavaScript 프로그램 아키텍처는 다음과 같아야 합니다(주로 이는 우리가 자주 호출하는 ASP.NET MVC가 아니라 JS 아키텍처입니다).

사용자 정의 위젯

모델

컨트롤러

템플릿 라이브러리/툴킷 애플리케이션 코어입니다.

프로그램을 여러 모듈로 개별적으로 캡슐화하거나 다른 디자인 패턴을 사용할 수도 있지만 이러한 구조가 아키텍처를 완전히 표현하는 경우 몇 가지 잠재적인 문제가 있을 수 있습니다. 중요 포인트:

1. 건축물에서 즉시 꺼내서 재사용할 수 있는 것이 몇 개나 되나요?

다른 코드에 의존하지 않는 별도의 모듈이 있나요? 그것은 독립적입니까? 사용 중인 코드 베이스로 이동하여 일부 모듈 코드를 무작위로 선택한 다음 새 페이지에 넣으면 즉시 사용할 수 있습니까? 원칙이면 충분하다고 생각하실 수도 있겠지만, 회사에서 이전에 중요한 프로그램을 많이 개발했다면 어느 날 갑자기 누군가가 이 프로젝트의 채팅 모듈이 좋다는 말을 하게 될 것입니다. 다른 프로젝트에 넣어보세요. 코드를 수정하지 않고 그냥 가져가서 사용할 수 있나요?


2. 시스템에서 다른 모듈에 의존해야 하는 모듈은 몇 개입니까?
시스템의 다양한 모듈이 긴밀하게 결합되어 있나요? 이 질문을 우려 사항으로 다루기 전에 모든 모듈이 종속성을 갖지 않아야 한다는 의미는 아니라는 점을 먼저 설명하겠습니다. 예를 들어, 세분화된 함수는 기본 함수에서 확장될 수 있습니다. . , 나는 서로 다른 기능 모듈 간의 종속성에 대해 이야기하고 있습니다. 이론적으로 모든 다른 기능 모듈은 너무 많은 종속성을 가져서는 안 됩니다.


3. 프로그램의 특정 부분이 잘못되어도 다른 부분은 작동할 수 있나요?

Gmail과 유사한 프로그램을 빌드해 보면 Gmail의 많은 모듈이 동적으로 로드되는 것을 볼 수 있습니다. 예를 들어 페이지 초기화 시 채팅 모듈이 로드되지 않고, 로드 후 오류가 발생하더라도 다른 부분은 로드되지 않습니다. 페이지가 로드되지 않습니다. 정상적으로 사용할 수도 있습니다.

4. 각 모듈을 쉽게 테스트할 수 있나요? 각 모듈은 수백만 명의 사용자가 있는 대규모 사이트에서 사용될 수도 있고 심지어 여러 사이트에서 사용될 수도 있으므로 모듈은 테스트, 즉 아키텍처 내부에 있든 아키텍처 외부에 있든 견딜 수 있어야 합니다. 다양한 환경에서 통과할 수 있는 대부분의 어설션을 포함하여 테스트하기 쉬워야 합니다.

장기적으로 생각하세요

대규모 프로그램을 구축할 때 가장 중요한 것은 한 달, 1년 후의 상황만 고려할 수는 없지만 변화 가능성도 고려하는 것입니다. 장기적으로? 개발자는 종종 별도의 로직을 다른 모듈에 캡슐화했음에도 불구하고 DOM 조작 코드를 프로그램에 너무 긴밀하게 바인딩합니다. 장기적으로 보면 왜 좋지 않습니까?

제 동료는 정밀한 아키텍처가 미래 시나리오에 적합하지 않을 수 있다고 말한 적이 있습니다. 이는 때때로 사실이지만 이를 수행하려면 많은 비용을 지불해야 합니다. 예를 들어 특정 성능, 보안, 디자인상의 이유로 Dojo, jQuery, Zepto, YUI 중 하나를 선택하고 교체해야 할 수도 있습니다. 이때 대부분의 모듈에는 비용과 시간이 필요한 종속성이 있습니다. . , 우리에겐 사람이 필요해요, 그렇죠?

일부 소규모 사이트에서는 괜찮지만 대규모 사이트에서는 다양한 모듈 간의 다양한 문제를 걱정하지 않고 보다 유연한 메커니즘을 제공해야 합니다. 이렇게 하면 비용과 시간이 절약됩니다.

요약하자면, 이제 전체 프로그램을 다시 작성하지 않고도 일부 라이브러리를 교체할 수 있다고 확신하시나요? 그렇지 않다면 아래에서 이야기할 내용이 귀하에게 더 적합할 것 같습니다.

많은 숙련된 JavaScript 개발자들이 몇 가지 핵심 사항을 제시했습니다.

JavaScriptMVC의 저자인 Justin Meyer는 다음과 같이 말했습니다.

대규모 프로그램을 구축하는 가장 큰 비결은 대규모 프로그램을 구축하지 않고 프로그램을 개별 구성 요소로 분할하는 것입니다. 각 작은 모듈을 테스트하고 크기를 조정한 다음 프로그램에 통합할 수 있도록 작은 모듈을 만듭니다.

고성능 JavaScript 웹사이트의 저자 Nicholas Zakas:
"핵심은 이것이 어떻게 성장할지 전혀 모른다는 점을 처음부터 인정하는 것입니다. 모든 것을 알지 못한다는 사실을 받아들일 때 시스템 설계를 시작합니다. 방어적으로 변경될 수 있는 핵심 영역을 식별하는데, 약간의 시간을 투자하면 매우 쉽습니다. 예를 들어, 다른 시스템과 통신하는 앱의 모든 부분이 변경될 가능성이 있다고 예상해야 합니다. -

단어 문제가 너무 많아서 문제가 많습니다. 정리하자면 모든 것은 가변적이므로 추상적이어야 합니다.

Rebecca Murphey, jQuery Fundamentals의 저자:
각 모듈 간의 연결이 가까울수록 재사용 가능성이 낮아지고 변경이 더 어려워집니다.

위의 중요한 사항은 건축물을 짓는 핵심 요소이며, 우리는 이를 항상 염두에 두어야 합니다.

브레인스토밍

느슨하게 결합된 아키텍처가 필요합니다. 모듈 간에는 종속성이 없으며 중간 계층이 해당 피드백 메시지를 인계받아 처리합니다.

예를 들어 온라인 베이커리 프로그램을 구축하기 위한 JavaScript가 있는 경우 모듈은 "빵 42개를 배달해야 합니다."라는 메시지를 보냅니다. 우리는 모듈이 보낸 메시지를 처리하기 위해 다음과 같이 다양한 레이어를 사용합니다.

모듈은 프로그램의 핵심에 직접 액세스하지 않습니다.
모듈은 다른 모듈을 직접 호출하거나 영향을 주지 않습니다.

이렇게 하면 오류가 발생하는 것을 방지할 수 있습니다. 특정 모듈 오류로 모든 모듈에 결함이 있습니다.

또 다른 문제는 보안입니다. 대부분의 사람들은 내부 보안이 문제라고 생각하지 않습니다. 우리는 프로그램이 공개인지 비공개인지 알고 있습니다. 보안에는 문제가 없습니다. 하지만 프로그램의 핵심에 액세스할 권한이 있는 모듈을 정의할 수 있는 방법이 있습니까? 예를 들어 채팅 모듈이 있는 경우 관리 모듈을 호출하지 않거나 DB 쓰기 권한이 있는 모듈을 호출하지 않기를 원합니다. 왜냐하면 이들 사이의 관계가 매우 취약하고 쉽게 이어질 수 있기 때문입니다. XSS 공격에. 각 모듈이 모든 작업을 수행할 수는 없지만 이는 대부분의 최신 아키텍처에서 JavaScript 코드의 문제입니다. 어떤 모듈이 승인된 부분에 액세스할 수 있는지 제어하기 위해 중간 계층을 제공합니다. 즉, 모듈은 가장 승인된 부분만 수행할 수 있습니다.

제안된 아키텍처

우리 기사의 초점은 여기에 있습니다. 이번에 제안된 아키텍처는 우리 모두에게 친숙한 모듈, 파사드 및 중재자 디자인 패턴을 사용합니다.

기존 모델과 달리, 각 모듈을 분리하기 위해 모듈이 일부 이벤트만 게시하도록 허용합니다. 중재자 모드는 이러한 모듈에서 메시지 메시지를 구독한 다음 알림의 응답을 제어할 수 있습니다. 각 모듈의 권한을 제한합니다.

우리가 주목해야 할 부분은 다음과 같습니다.
1 디자인 패턴
1.1 모듈 이론
1.1.1 개요
1.1.2 모듈 패턴
1.1.3 객체 자체 얼굴
1.1.4 CommonJS 모듈
1.2 Facade 모드
1.3 Mediator 패턴
2는 아키텍처에 적용됩니다.
2.1 Facade - 핵심 추상화
2.2 Mediator - 프로그램 핵심
2.3 긴밀하게 협력합니다.

모듈 이론

모든 사람은 어느 정도 모듈 코드와 모듈을 사용할 수 있습니다. 완전하고 강력한 프로그램 아키텍처의 일부입니다. 각 모듈은 별도의 목적으로 만들어졌습니다. Gmail로 돌아가서 예를 들어 보겠습니다. 채팅 모듈은 별도의 부분처럼 보이지만 실제로는 별도의 하위 구성 요소가 많이 있습니다. 예를 들어, 내부의 표현 모듈은 실제로 이메일을 보내는 창에서도 사용되는 별도의 하위 모듈입니다.

다른 하나는 모듈을 동적으로 로드, 삭제 및 교체할 수 있다는 것입니다.

JavaScript에는 모듈을 구현하는 여러 가지 방법이 있습니다. 가장 잘 알려진 방법은 모듈 모드와 객체 리터럴입니다. 이미 익숙하다면 이 섹션을 무시하고 CommonJS 부분으로 바로 이동하세요.

모듈 패턴

모듈 패턴은 중괄호를 통해 개인 변수, 메서드 및 상태를 캡슐화할 수 있으며, 일반적으로 이 디자인 패턴에서는 전역 개체에 직접 액세스할 수 없습니다. 하나의 API만 반환되고 다른 모든 콘텐츠는 비공개로 캡슐화됩니다.

또한 이 패턴은 자체 실행 함수 표현식과 유사하지만 유일한 차이점은 모듈이 객체를 반환하는 반면, 자체 실행 함수 표현식은 함수를 반환한다는 것입니다.

우리 모두 알고 있듯이 JavaScript에는 다른 언어처럼 액세스 수정자가 없습니다. 각 필드나 메소드에 대해 비공개 및 공개 수정자를 선언할 수 없습니다. 이는 일부 공용 메소드가 포함된 객체를 반환하는 것입니다. 이러한 메소드에는 내부 객체를 호출하는 기능이 있습니다.

다음 코드를 보세요. 선언에는 전역 개체 basketModule이 포함되어 있습니다. 따라서 전체 프로그램은 이 개인 배열에 액세스할 수 없습니다. 여기에는 addItem, getItemCount, getTotal 등 세 가지 메서드가 포함되어 있습니다. 이 세 가지 메서드는 개인 바구니 배열에 액세스할 수 있습니다.

var basketModule = (function() {
var basket = []; //private
return { //exposed to public
  addItem: function(values) {
    basket.push(values);
  },
  getItemCount: function() {
    return basket.length;
  },
  getTotal: function(){
    var q = this.getItemCount(),p=0;
    while(q--){
    p+= basket[q].price;
    }
    return p;
  }
 }
}());
로그인 후 복사

또한 우리가 반환하는 객체는 basketModule에 직접 할당되므로 다음과 같이 사용할 수 있습니다.

//basketModule is an object with properties which can also be methods
basketModule.addItem({item:'bread',price:0.5});
basketModule.addItem({item:'butter',price:0.3});
 
console.log(basketModule.getItemCount());
console.log(basketModule.getTotal());
 
//however, the following will not work:
console.log(basketModule.basket);// (undefined as not inside the returned object)
console.log(basket); //(only exists within the scope of the closure)
로그인 후 복사

다양한 인기 라이브러리(예: Dojo, jQuery)에서 어떻게 수행합니까?

Dojo

Dojo는 클래스 스타일 선언 메소드를 제공하기 위해 dojo.declare를 사용하여 모듈 모드를 구현할 수 있습니다. 예를 들어, store 네임스페이스 아래에 바구니 객체를 선언하려는 경우입니다. , 다음과 같이 할 수 있습니다:

//traditional way
var store = window.store || {};
store.basket = store.basket || {};
 
//using dojo.setObject
dojo.setObject("store.basket.object", (function() {
  var basket = [];
  function privateMethod() {
    console.log(basket);
  }
  return {
    publicMethod: function(){
      privateMethod();
    }
   };
}()));
로그인 후 복사

dojo.provide와 함께 사용하면 매우 강력합니다.

YUI

다음 코드는 YUI의 원래 구현입니다.

YAHOO.store.basket = function () {

 //"private" variables:
 var myPrivateVar = "I can be accessed only within YAHOO.store.basket .";

 //"private" method:
 var myPrivateMethod = function () {
 YAHOO.log("I can be accessed only from within YAHOO.store.basket");
 }

 return {
 myPublicProperty: "I'm a public property.",
 myPublicMethod: function () {
  YAHOO.log("I'm a public method.");

  //Within basket, I can access "private" vars and methods:
  YAHOO.log(myPrivateVar);
  YAHOO.log(myPrivateMethod());

  //The native scope of myPublicMethod is store so we can
  //access public members using "this":
  YAHOO.log(this.myPublicProperty);
 }
 };

} ();
로그인 후 복사

jQuery

jQuery에는 모듈 패턴의 구현이 많이 있습니다. 다른 예인 라이브러리 함수를 살펴보겠습니다. 선언 새 라이브러리를 생성한 후, 라이브러리 생성 시 document.ready의 init 메소드를 자동으로 실행합니다.

function library(module) {
  $(function() {
    if (module.init) {
      module.init();
    }
  });
  return module;
}
 
var myLibrary = library(function() {
  return {
    init: function() {
      /*implementation*/
      }
  };
}());
로그인 후 복사

Object self-facet

Object self-facet은 중괄호를 사용하여 선언되며, public/privateness에 크게 신경 쓰지 않는다면 new 키워드를 사용할 필요가 없습니다. 모듈의 속성 필드 중 이 방법을 사용할 수 있지만 이 방법은 JSON과 다르다는 점에 유의하세요. 객체 자체 얼굴: var item={name: "tom", value:123} JSON: var item={"name":"tom", "value":123}.

var myModule = {
 myProperty: 'someValue',
 //object literals can contain properties and methods.
 //here, another object is defined for configuration
 //purposes:
 myConfig: {
 useCaching: true,
 language: 'en'
 },
 //a very basic method
 myMethod: function () {
 console.log('I can haz functionality?');
 },
 //output a value based on current configuration
 myMethod2: function () {
 console.log('Caching is:' + (this.myConfig.useCaching) ? 'enabled' : 'disabled');
 },
 //override the current configuration
 myMethod3: function (newConfig) {
 if (typeof newConfig == 'object') {
  this.myConfig = newConfig;
  console.log(this.myConfig.language);
 }
 }
};

 
myModule.myMethod(); //I can haz functionality
myModule.myMethod2(); //outputs enabled
myModule.myMethod3({ language: 'fr', useCaching: false }); //fr
로그인 후 복사

CommonJS

여기서는 CommonJS 도입에 대해 많이 언급하지 않겠습니다. 이전의 많은 기사에서 여기서 언급하고 싶은 것은 CommonJS 표준에 내보내기 및 요구 사항이 있다는 것입니다. .exports는 로드할 모듈을 나타내고, require는 로드된 모듈이 다른 모듈에 의존해야 하며 또한 로드되어야 함을 나타냅니다.

/*
Example of achieving compatibility with AMD and standard CommonJS by putting boilerplate around the standard CommonJS module format:
*/
 
(function(define){
  define(function(require,exports){
    // module contents
    var dep1 = require("dep1");
    exports.someExportedFunction = function(){...};
    //...
  });
})(typeof define=="function"?define:function(factory){factory(require,exports)});
로그인 후 복사

CommonJS 표준 모듈 로딩 구현이 많이 있습니다. 제가 선호하는 것은 RequireJS입니다. 모듈 및 관련 종속 모듈을 매우 잘 로드할 수 있나요? 예를 들어, 이미지를 ASCII 코드로 변환해야 하는 경우 먼저 인코더 모듈을 로드한 다음 encodeToASCII 메서드를 가져옵니다. 이론적으로 코드는 다음과 같아야 합니다.

var encodeToASCII = require("encoder").encodeToASCII;
exports.encodeSomeSource = function(){
  //其它操作以后,然后调用encodeToASCII
}
로그인 후 복사

但是上述代码并没用工作,因为encodeToASCII函数并没用附加到window对象上,所以不能使用,改进以后的代码需要这样才行:

define(function(require, exports, module) {
  var encodeToASCII = require("encoder").encodeToASCII;
    exports.encodeSomeSource = function(){
    //process then call encodeToASCII
  }
});
로그인 후 복사

CommonJS 潜力很大,但是由于大叔不太熟,所以就不过多地介绍了。

Facade模式

Facade模式在本文架构里占有重要角色,关于这个模式很多JavaScript类库或者框架里都有体现,其中最大的作用,就是包括High level的API,以此来隐藏具体的实现,这就是说,我们只暴露接口,内部的实现我们可以自己做主,也意味着内部实现的代码可以很容易的修改和更新,比如今天你是用jQuery来实现的,明天又想换YUI了,这就非常方便了。

下面这个例子了,可以看到我们提供了很多私有的方法,然后通过暴露一个简单的 API来让外界执行调用内部的方法:

var module = (function () {
 var _private = {
 i: 5,
 get: function () {
  console.log('current value:' + this.i);
 },
 set: function (val) {
  this.i = val;
 },
 run: function () {
  console.log('running');
 },
 jump: function () {
  console.log('jumping');
 }
 };
 return {
 facade: function (args) {
  _private.set(args.val);
  _private.get();
  if (args.run) {
  _private.run();
  }
 }
 }
} ());

module.facade({run:true, val:10});
//outputs current value: 10, running
로그인 후 복사

Facade和下面我们所说的mediator的区别是,facade只提供现有存在的功能,而mediator可以增加新功能。

Mediator模式

讲modiator之前,我们先来举个例子,机场飞行控制系统,也就是传说中的塔台,具有绝对的权利,他可以控制任何一架飞机的起飞和降落时间以及地方,而飞机和飞机之前不允许通信,也就是说塔台是机场的核心,mediator就相当于这个塔台。

mediator就是用在程序里有多个模块,而你又不想让各个模块有依赖的话,那通过mediator模式可以达到集中控制的目的。实际场景中也是,mediator封装了很多不想干的模块,让他们通过mediator联系在一起,同时也松耦合他们,使得他们之间必须通过mediator才能通信。

那mediator模式的优点是什么?那就是解耦,如果你之前对观察者模式比较了解的话,那理解下面的mediator图就相对简单多了,下图是一个high level的mediator模式图:

대규모 JavaScript 애플리케이션 아키텍처 디자인 패턴(고급)

想想一下,各模块是发布者,mediator既是发布者又是订阅者。

Module 1向Mediator广播一个实际,说需要做某事
Mediator捕获消息以后,立即启动处理该消息需要使用的Module 2,Module 2处理结束以后返回信息给Mediator
与此同时,Mediator也启动了Module 3,当接受Module 2 返回消息的时候自动记录日志到Module 3里

可以看到,各模块之间并没有通信,另外Mediator也可以实现监控各模块状态的功能,例如如果Module 3出错了,Mediator可以暂时只想其它模块,然后重启Module 3,然后继续执行。

回顾一下,可以看到,Mediator的优点是:松耦合的模块由同一的Mediator来控制,模块只需要广播和监听事件就可以了,而模块之间不需要直接联系,另外,一次信息的处理可以使用多个模块,也方便我们以后统一的添加新的模块到现有的控制逻辑里。

确定是:由于所有的模块直接都不能直接通信,所有相对来说,性能方面可能会有少许下降,但是我认为这是值得的。

我们根据上面的讲解来一个简单的Demo:

var mediator = (function(){
 var subscribe = function(channel, fn){
 if (!mediator.channels[channel]) mediator.channels[channel] = [];
 mediator.channels[channel].push({ context: this, callback: fn });
 return this;
 },
 
 publish = function(channel){
 if (!mediator.channels[channel]) return false;
 var args = Array.prototype.slice.call(arguments, 1);
 for (var i = 0, l = mediator.channels[channel].length; i < l; i++) {
  var subscription = mediator.channels[channel][i];
  subscription.callback.apply(subscription.context, args);
 }
 return this;
 };
 
 return {
 channels: {},
 publish: publish,
 subscribe: subscribe,
 installTo: function(obj){
  obj.subscribe = subscribe;
  obj.publish = publish;
 }
 };
 
}());
로그인 후 복사

然后有2个模块分别调用:

//Pub/sub on a centralized mediator
 
mediator.name = "tim";
mediator.subscribe(&#39;nameChange&#39;, function(arg){
 console.log(this.name);
 this.name = arg;
 console.log(this.name);
});
 
mediator.publish(&#39;nameChange&#39;, &#39;david&#39;); //tim, david
 
 
//Pub/sub via third party mediator
 
var obj = { name: &#39;sam&#39; };
mediator.installTo(obj);
obj.subscribe(&#39;nameChange&#39;, function(arg){
 console.log(this.name);
 this.name = arg;
 console.log(this.name);
});
 
obj.publish(&#39;nameChange&#39;, &#39;john&#39;); //sam, john
로그인 후 복사

应用Facade: 应用程序核心的抽象

一个facade是作为应用程序核心的一个抽象来工作的,在mediator和模块之间负责通信,各个模块只能通过这个facade来和程序核心进行通信。作为抽象的职责是确保任何时候都能为这些模块提供一个始终如一的接口(consistent interface),和sendbox controller的角色比较类似。所有的模块组件通过它和mediator通信,所以facade需要是可靠的,可信赖的,同时作为为模块提供接口的功能,facade还需要扮演另外一个角色,那就是安全控制,也就是决定程序的哪个部分可以被一个模块访问,模块组件只能调用他们自己的方法,并且不能访问任何未授权的内容。例如,一个模块可能广播dataValidationCompletedWriteToDB,这里的安全检查需要确保该模块拥有数据库的写权限。

总之,mediator只有在facade授权检测以后才能进行信息处理。

应用Mediator:应用程序的核心

Mediator는 애플리케이션의 핵심 역할을 담당합니다. 그의 책임에 대해 간단히 이야기하겠습니다. 핵심 작업은 모듈의 수명 주기를 관리하는 것입니다. 이 코어는 들어오는 정보를 캡처할 때 프로그램이 이를 처리하는 방법, 즉 시작하거나 중지할 모듈을 결정해야 합니다. 모듈이 시작되면 애플리케이션 코어가 실행 여부(예: DOM이 준비되었을 때 실행해야 하는지 여부)를 결정하지 않고도 자동으로 실행될 수 있어야 하므로 모듈 자체에서 결정을 내려야 합니다.

어떤 상황에서 모듈이 중지되는지에 대한 질문이 여전히 있을 수 있습니다. 프로그램이 모듈이 실패했거나 오류가 발생했음을 감지하면 구성 요소를 다시 시작할 수 있도록 모듈의 메서드가 계속 실행되지 않도록 결정을 내려야 합니다. 주요 목적은 사용자를 개선하는 것입니다. 경험.

또한 코어는 다른 기능에 영향을 주지 않고 동적으로 모듈을 추가하거나 삭제할 수 있어야 합니다. 일반적인 예로는 페이지 로딩 초기에는 모듈을 사용할 수 없지만, 사용자 작업 후에는 Gmail의 채팅 기능과 마찬가지로 모듈을 동적으로 로딩하고 실행해야 하는 경우가 성능 최적화 측면에서 필요합니다. 아주 좋아. 이해해.

예외 오류 처리도 애플리케이션 코어에서 처리됩니다. 또한 각 모듈이 정보를 브로드캐스트할 때 모든 오류를 코어에 브로드캐스트하므로 프로그램 코어는 상황에 따라 이러한 모듈을 중지/다시 시작할 수 있습니다. 이는 느슨하게 결합된 아키텍처의 중요한 부분이기도 합니다. 중재자를 통해 게시/구독을 사용하면 모듈을 수동으로 변경할 필요가 없습니다.

Assembled

각 모듈에는 처리해야 할 정보가 있는 경우 아래 QA 섹션인 모듈에 언급된 대로 프로그램에 알리기 위한 정보를 공개합니다(이것이 주요 책임입니다). 일부 DOM 도구 작업 방법에 의존할 수 있지만 시스템의 다른 모듈에 의존해서는 안 됩니다. 모듈은 다음 사항에 초점을 맞춰서는 안 됩니다.

1. 이 모듈에서 게시한 정보를 구독하는 객체 또는 모듈 2. 이러한 객체 클라이언트는 최종 객체 또는 서버측 객체입니다
3. 귀하의 정보를 구독하는 객체 수

대규모 JavaScript 애플리케이션 아키텍처 디자인 패턴(고급)

Facade는 애플리케이션의 핵심을 추상화하고 모듈 간의 직접적인 통신을 피하며 각 모듈의 정보를 구독합니다. 인증 감지를 통해 각 모듈에 별도의 라이센스가 있는지 확인합니다.

대규모 JavaScript 애플리케이션 아키텍처 디자인 패턴(고급)

Mediator(애플리케이션 코어)는 중재자 모드를 사용하여 게시/구독 관리자 역할을 담당하며, 잘못된 모듈을 동적으로 로드하고 다시 시작할 수 있습니다.

대규모 JavaScript 애플리케이션 아키텍처 디자인 패턴(고급)

이 아키텍처의 결과는 느슨하게 결합된 애플리케이션으로 인해 모듈 간에 종속성이 없으며 각 모듈을 다른 프로젝트에서 쉽게 재사용할 수 있고 다른 프로젝트에서도 사용할 수 있다는 것입니다. . 프로그램에 영향을 주지 않고 동적으로 추가하고 삭제합니다.

게시/구독 구독 확장: 자동 이벤트 등록

자동 등록 이벤트와 관련하여 특정 명명 규칙을 따라야 합니다. 예를 들어, 모듈이 messageUpdate라는 이벤트를 게시하면 messageUpdate 메서드가 있는 모듈이 포함된 모든 이벤트가 발생합니다. 자동으로 실행됩니다. 특정 구현 방법에 대해서는 내 다른 게시물인 jQuery 사용자 정의 바인딩의 Magic 업그레이드 버전을 읽어볼 수 있습니다.

QA1. 파사드나 유사한 샌드박스 모드를 사용하지 않는 것이 가능한가요?

아키텍처의 개요에서는 Facade가 인증 확인 기능을 구현할 수 있다고 제안하지만 실제로는 중재자가 이를 수행하는 것이 전적으로 가능합니다. 경량 아키텍처가 해야 할 일은 실제로 거의 동일합니다. 각 모듈이 애플리케이션의 핵심에 직접 연결되어 있는지 확인하십시오. 통신에는 문제가 없습니다.

2. 모듈이 직접 종속성을 가질 수 없도록 개선했습니다. 이는 제3자 라이브러리(예: jQuery)에 의존할 수 없다는 의미입니다.

이것은 실제로 양면 문제입니다. 위에서 언급했듯이 모듈에는 일부 하위 모듈이 있거나 기본 DOM 조작 도구 클래스와 같은 기본 모듈이 있을 수 있습니다. 예. , 하지만 쉽게 교체할 수 있는지 확인하시기 바랍니다.

3. 이 아키텍처가 마음에 들어서 사용해보고 싶습니다. 참고할 수 있는 코드 샘플이 있나요?

모두가 참고할 수 있도록 코드 샘플을 얻을 예정인데, 그 전에 Andrew Burgees의 Writing Modular JavaScript 게시물을 참고하시면 됩니다.

4. 모듈이 애플리케이션 코어와 직접 통신해야 하는 경우 가능합니까?

기술적으로 말하면 현재 모듈이 애플리케이션 코어와 직접 통신할 수 없는 이유는 없지만 대부분의 애플리케이션 경험에서는 여전히 필요하지 않습니다. 이 아키텍처를 선택했으므로 아키텍처에서 정의한 규칙을 준수해야 합니다.

위 내용은 제가 여러분을 위해 정리한 내용입니다. 앞으로 도움이 되길 바랍니다.

관련 기사:

JS의 이벤트에 대한 자세한 답변(그래픽 튜토리얼)

JSON 개체를 문자열로 변환(코드가 첨부된 자세한 답변)

JS의 이벤트 버블링 및 이벤트 캡처(그림 및 텍스트 튜토리얼, 단순한 폭력)

위 내용은 대규모 JavaScript 애플리케이션 아키텍처 디자인 패턴(고급)의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

관련 라벨:
원천:php.cn
본 웹사이트의 성명
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.
인기 튜토리얼
더>
최신 다운로드
더>
웹 효과
웹사이트 소스 코드
웹사이트 자료
프론트엔드 템플릿