programing

RequireJS를 사용하여 전역 객체 또는 싱글 톤을 어떻게 전달합니까?

javaba 2021. 1. 15. 19:09
반응형

RequireJS를 사용하여 전역 객체 또는 싱글 톤을 어떻게 전달합니까?


메인 페이지 수준에서 코드를 작성하고 있고 2 개의 종속성이 동일한 객체 인스턴스를 필요로하며이를 종속성으로 명시한다고 가정 해 보겠습니다. 이에 대해 적절한 방법은 무엇입니까?

기본적으로 내가 원하는 것은 "이 종속성이로드되지 않은 경우 ...로드하십시오. 그렇지 않으면 이미로드 된 동일한 인스턴스를 사용하고 해당 인스턴스를 전달하십시오."라고 말하는 것입니다.


모듈 수준 변수로 만들 것입니다. 예를 들면

// In foo.js
define(function () {
    var theFoo = {};

    return {
        getTheFoo: function () { return theFoo; }
    };
});

// In bar.js
define(["./foo"], function (foo) {
    var theFoo = foo.getTheFoo(); // save in convenience variable

    return {
        setBarOnFoo: function () { theFoo.bar = "hello"; }
    };
}

// In baz.js
define(["./foo"], function (foo) {
    // Or use directly.
    return {
        setBazOnFoo: function () { foo.getTheFoo().baz = "goodbye"; }
    };
}

// In any other file
define(["./foo", "./bar", "./baz"], function (foo, bar, baz) {
    bar.setBarOnFoo();
    baz.setBazOnFoo();

    assert(foo.getTheFoo().bar === "hello");
    assert(foo.getTheFoo().baz === "goodbye");
};

싱글 톤에 대한 API를 제공하십시오.

그리고 느리게로드되었는지 확인하십시오. 가장 쉬운 방법은 크로스 브라우저 도우미를 제공하는 밑줄과 같은 추상화 라이브러리를 사용하는 것입니다. 다른 옵션은 ES5 Object.defineProperty 또는 사용자 정의 getter / setter입니다.

이 경우 _.once생성자의 결과가 첫 번째 호출 후 캐시되도록 보장하며 기본적으로 지연로드합니다.

define(function() {
    var constructor = _.once(function() { 
        ...
    });

    return {
        doStuffWithSingleton: function() {
            constructor().doStuff();
        }
    };

});

_.once 밑줄에서.


캡슐화에 대한 Raynos의 우려와 메시징 서비스에 대한 몇 가지 메서드를 공개하고자하는 OP의 설명을 결합하면 이것이 올바른 방법이라고 생각합니다.

// In messagingServiceSingleton.js
define(function () {
    var messagingService = new MessagingService();

    return {
        notify: messagingService.listen.bind(messagingService),
        listen: messagingService.notify.bind(messagingService)
    };
});

// In bar.js
define(["./messagingServiceSingleton"], function (messagingServiceSingleton) {
    messagingServiceSingleton.listen(/* whatever */);
}

// In baz.js
define(["./messagingServiceSingleton"], function (messagingServiceSingleton) {
    messagingServiceSingleton.notify(/* whatever */);
}

Function.prototype.bind모든 브라우저에있는 것은 아니므로 Mozilla가 제공 하는 것과 같은 폴리 필을 포함해야 합니다 .

대체 (내 생각에는 아마도 더 나은) 접근 방식은 메시징 서비스 객체 자체를 모듈로 만드는 것입니다. 이것은 다음과 같이 보일 것입니다.

// In messagingService.js
define(function () {
    var listenerMap = {};

    function listen(/* params */) {
        // Modify listenerMap as appropriate according to params.
    }
    function notify(/* params */) {
        // Use listenerMap as appropriate according to params.
    }

    return {
        notify: notify
        listen: listen
    };
});

모듈을 사용하는 모든 사람에게 동일한 notifylisten메서드를 노출하고 항상 동일한 개인 listenerMap 변수를 참조하므로 원하는대로 수행해야합니다. 또한에 대한 필요성을 Function.prototype.bind제거하고 메시징 서비스 자체와 단일 사용을 강제하는 모듈 간의 불필요한 구분을 제거합니다.


다음은 모듈 자체가 해당 모듈 내의 변수가 아닌 공유 변수 인 버전입니다.

define('foo', [], {bar: "this text will be overwritten"});

define('bar', ["foo"], function (foo) {
    return {
        setBarOnFoo: function () { foo.bar = "hello"; }
    };
});

define('baz', ["foo"], function (foo) {
    return {
        setBazOnFoo: function () { foo.baz = "goodbye"; }
    };
});

require(["foo", "bar", "baz"], function (foo, bar, baz) {
    bar.setBarOnFoo();
    baz.setBazOnFoo();

    $('#results').append(foo.bar + ' ' + foo.baz);
});​​​

// reads: hello goodbye

As a variation of Domenic's answer, you can use the 'exports' magic module to automatically generate a reference for the module -- "Properties added to the exports object will be on the public interface of the module, no need to return any value." This avoids having to call the getTheFoo() function to obtain a reference.

// In foo.js
define(['exports'], function (foo) {
   foo.thereCanBeOnlyOne = true; 
});

// In bar.js
define(["exports", "./foo"], function (bar, foo) {
  bar.setBarOnFoo = function () { foo.bar = "hello"; };
});

// in baz.js
define(["exports", "./foo"], function (baz, foo) {
  baz.setBazOnFoo = function () { foo.baz = "goodbye"; };
});

// In any other file
define(["./foo", "./bar", "./baz"], function (foo, bar, baz) {
  bar.setBarOnFoo();
  baz.setBazOnFoo();

  assert(foo.bar === "hello");
  assert(foo.baz === "goodbye");
  assert(foo.thereCanBeOnlyeOne);
});

To address the comment below, I personally have found the above convention to be useful. Your mileage may vary, but feel free to adopt the convention if you think it is useful. The convention boils down to these two rules:

  • Declare 'exports' as the first dependency in the define array.
  • Name the parameter in the function after the JavaScript file.

Using the name of file, e.g. for foo.js name the variable 'foo', increases the readability of the code as most developers will define 'foo' as the parameter for the foo.js dependency. When scanning the code or using grep, it is easy to find all references to 'foo' use both inside and outside the module and it makes it easy to pick out what the module is exposing to the public. For example, renaming bar.setBarOnFoo to bar.setFooBar is much easier if the declaration in the bar.js module mirrors the usage in other files. A simple search and replace of bar.setBarOnFoo to bar.setFooBar across all files will accomplish the task.


I was in this scenario:

For different reasons I needed to call a function that was on a requirejs module, but the click that fired that call was out of require.

The way I fixed this was creating a requirejs modure that writes over the window object.

define("one", [], function() {
    window.popupManager = (function () {
            console.log ('aca');

        var popUpManager = function () {
            self = this;

            self.CallMe = function ()
            {
                alert ('someone calls');
            };
        };
        return new popUpManager();
    })();
});
require(['one']);

window.popupManager.CallMe();

This way if any piece of code that is out of the require spectrum (I know it shouldn't be this way) can call functions of this require that writes over the window object.

I really know this is not an "elegant" solution, but it may help you in case of an emergency.

ReferenceURL : https://stackoverflow.com/questions/5608685/using-requirejs-how-do-i-pass-in-global-objects-or-singletons-around

반응형