api.modifyClass가 가끔(!) 작동하지 않음

수정: 버그로 재분류했습니다.
전체 재현 방법은 아래에 있습니다.

테마 컴포넌트에서 api.modifyClass를 사용 중입니다.

대부분의 페이지에서는 정상적으로 작동하지만, 일부 주제에서는 페이지를 새로 고침할 때 사용자 모델에 해당 속성이 추가되지 않습니다. 대부분의 주제에서는 작동하는데 일부 주제에서는 작동하지 않는 이유, 혹은 작동하지 않는 주제들이 어떤 공통점을 가지고 있는지 파악하지 못하고 있습니다.

여기서 제가 무엇을 잘못하고 있는지 이해하시는 분 계신가요?

요약: modifyClass 아래에 모델을 위한 api.container.lookup을 추가하면 이 문제를 우회할 수 있습니다.

1개의 좋아요

아, 맞다! 혹시 이거 아닐까요?

pluginId를 추가해야 하는 것 같습니다.

     <script type="text/discourse-plugin" version="0.1">
    api.modifyClass('model:user', {
      pluginId: 'my-plugin', 
      testProperty: function() {
        return 1;
      } 
    });
</script>

나중 버전에서는 필수 항목입니다. 실제로 어제 몇몇 테마에 이 항목을 추가하기 위해 PR을 제출했습니다. 드디어 플러그인/테마 개발자가 되는 것 같네요.

2개의 좋아요

제이, 감사합니다! 실제로 제 테스트 인스턴스에서 효과가 있었어요.
하지만 unfortunately, 만능 해결책은 아니고 문제는 여전히 남아 있어요 :frowning:

1개의 좋아요

네, pluginId는 수정이 두 번 적용되는 것을 방지하기 위한 것으로 생각됩니다. 이것이 없다면 한 번도 실행되지 않은 이유를 설명할 수 없지 않나요?

1개의 좋아요

아니, 정말. 뭔가 아는 줄 알았는데. :crying_cat_face:

혹시 다른 곳에서 클래스를 수정하고 있어서, 누가 먼저 수정하는지에 따라 레이스 컨디션이 발생하는 건가 싶었습니다. 하지만 자바스크립트는 여전히 저에게 미스터리입니다.

2개의 좋아요

여전히 코드 관련 문제이므로 언급하는 것은 당연합니다.

1개의 좋아요

네, 저도 그 생각이 났습니다. 하지만 이 테스트 사이트에서는 이 것이 유일한 테마 컴포넌트임에도 불구하고 여전히 실패합니다.

1개의 좋아요

궁금한 점이 하나 있는데, 만약 이 코드를 다음 경로에 있는 테마 컴포넌트에 추가하면:

  • /javascripts/discourse/initializers/test-init.js.es6

동작이 달라지거나 개선될까요?

이 두 가지가 의미론적으로 동일한지 확신이 서지 않습니다 …

… 이론적으로는 브라우저가 새로고침될 때 둘 다 평가되어야 하며, 그 시점 이후에는 수정 사항이 이미 적용되었으므로 라우트 전환 시 레이스 컨디션은 무의미해야 합니다 …

1개의 좋아요

아니요, 동작은 동일합니다.

javascripts/discourse-test/initializers/initialize-discourse-test.js.es6를 사용하여 테마 컴포넌트를 만들었습니다:

import { withPluginApi } from "discourse/lib/plugin-api";

export default {
  name: 'discourse-test-initializer',
  initialize(){
    console.log('here1');
    withPluginApi("0.1", api => {
      console.log('here2');

      api.modifyClass('model:user', {
        pluginId: 'test',
        testFunction: function() {
          console.log('here3');
          return 2;
        }
      });

    });
  }
}

모든 페이지에서 다음과 같이 출력됩니다.

here1
here2

일부 토픽에서는 콘솔에 Discourse.currentUser.testFunction()을 입력하면 작동하며 here3과 2가 출력됩니다.

일부 토픽에서는 작동하지 않습니다(Uncaught TypeError: Discourse.currentUser.testFunction is not a function).

2개의 좋아요

네, 도움이 되는 게시글에 대한 알림을 확인했는데, 해당 게시글은 이미 삭제된 상태였습니다.
제안은 작동하지 않았지만, 문제를 해결하는 데 도움이 되는 단서를 제공해 주었습니다.

다음 스니펫을 작동하지 않는 코드 아래에 추가하면 제가 겪고 있던 문제가 일관되게 해결되었습니다. 이 방법은 안정 버전(stable)과 테스트 통과 버전(tests-passed) 모두에서 여러 독립적인 포럼을 통해 테스트해 보았습니다. 이 문제를 #contribute:bug로 재분류해야 한다고 생각합니다 …

<script type="text/discourse-plugin" version="0.1">
const userModel = api.container.lookup("model:user");
</script>

@Johani 도움 주셔서 감사합니다!

2개의 좋아요

이를 버그로 재분류합니다.

플러그인 API 코드인 app/assets/javascripts/discourse/app/lib/plugin-api.js에 console.log를 추가하여 modifyClass가 호출될 때마다 로그를 기록하도록 했습니다.

어딘가에 충돌이 없는지 확인하기 위해 모든 외부 플러그인을 제거했습니다.

재현 방법:

  • stable에서 빈 포럼을 생성합니다(Ember CLI가 없는 상태). tests-passed(Ember CLI 없음)에서도 작동하지 않습니다. Ember CLI와 함께 테스트하지는 않았습니다.

  • 다음 내용을 Common - Head에 추가한 테마 컴포넌트를 추가합니다

#1 작동

<script type="text/discourse-plugin" version="0.1">
    api.modifyClass('model:user', {
      pluginId: 'test-tc',
      testFunction: function() {
        return 1;
      } 
    });
</script>
  • 홈 페이지를 로드합니다

  • 콘솔에 modifyClass called for model:user _application-08d9058ddd37ba80992f770509f4919ad0738a17f14fb85167b1dc1f32f8b56e.js:23490:16 Object { pluginId: "test-tc", testFunction: testFunction() }가 표시됩니다

  • 콘솔에 Discourse.currentUser.testFunction()을 입력합니다

  • "1"이 출력됩니다

#2 실패

  • 예를 들어 'Welcome to Discourse’와 같은 토픽으로 이동하여 페이지를 새로고침합니다
  • 콘솔에 동일한 “modifyClass called” 로그가 표시됩니다
  • 콘솔에 Discourse.currentUser.testFunction()을 입력합니다
  • Uncaught TypeError: Discourse.currentUser.testFunction is not a function가 출력됩니다

#3 경고와 함께 실패

  • 테마 컴포넌트 맨 위에 한 줄을 추가하여 다음과 같은 모양으로 만듭니다:
<script type="text/discourse-plugin" version="0.1">
    const userModel = api.container.lookup("model:user");

    api.modifyClass('model:user', {
      pluginId: 'test-tc',
      testFunction: function() {
        return 1;
      } 
    });

</script>
  • 예를 들어 'Welcome to Discourse’와 같은 토픽으로 이동하여 페이지를 새로고침합니다
  • 콘솔에 동일한 “modifyClass called” 로그가 표시됩니다
  • 콘솔에 경고 "model:user" was already cached in the container. Changes won't be applied.가 표시됩니다
  • 콘솔에 Discourse.currentUser.testFunction()을 입력합니다
  • Uncaught TypeError: Discourse.currentUser.testFunction is not a function가 출력됩니다

#4 작동

  • lookup 줄을 테마 컴포넌트 하단으로 이동하여 다음과 같은 모양으로 만듭니다:
<script type="text/discourse-plugin" version="0.1">
    api.modifyClass('model:user', {
      pluginId: 'test-tc',
      testFunction: function() {
        return 1;
      } 
    });

    const userModel = api.container.lookup("model:user");
</script>
  • 예를 들어 'Welcome to Discourse’와 같은 토픽으로 이동하여 페이지를 새로고침합니다
  • 콘솔에 동일한 “modifyClass called” 로그가 표시됩니다
  • 콘솔에 Discourse.currentUser.testFunction()을 입력합니다
  • "1"이 출력됩니다 :partying_face:
4개의 좋아요

다시 살펴봅니다:

Discourse 2.8 이상에서 Discourse.User.current().testFunction()을 사용할 때, 경우 #2가 여전히 실패합니다.

1개의 좋아요

modifyClass에서도 문제가 발생하고 있는데, 관련이 있는지 확실하지 않습니다: Issues overriding getters in a controller (3.0.0)

이러한 상황에 대한 경고 메시지를 개선했습니다:

또한 원인과 해결 방법을 설명하는 문서를 작성했습니다:

이로써 이 주제에 대한 모든 우려 사항을 해결할 수 있을 것으로 생각합니다. 그렇지 않다면 실패하는 코드 예시를 공유해 주시면 확인해 보겠습니다.

11개의 좋아요

이 주제는 3일 후 자동으로 닫혔습니다. 새로운 답글은 더 이상 허용되지 않습니다.