IT박스

플럭스 상점 또는 조치 (또는 둘 다)가 외부 서비스와 접촉해야합니까?

itboxs 2020. 7. 11. 11:07
반응형

플럭스 상점 또는 조치 (또는 둘 다)가 외부 서비스와 접촉해야합니까?


상점이 자체 상태를 유지하고 네트워크 및 데이터 스토리지 서비스를 호출 할 수있는 기능이있는 경우 (이 경우 조치는 단순한 메시지 전달자,

-또는-

... 저장소는 조치에서 불변 데이터를 바보로받는 사람이어야하며 (및 조치는 외부 소스간에 데이터를 페치 / 송신하는 것이어야합니까?)이 경우 스토어는 뷰 모델로 작동하며 집계 / 필터링 할 수 있습니다. 액션에 의해 제공된 불변 데이터에 대한 자체 상태 기반을 설정하기 전에

그것은 둘 중 하나가 아닌 하나 또는 다른 것이어야한다고 생각합니다. 그렇다면 왜 다른 하나보다 선호 / 권장됩니까?


나는 플럭스 패턴이 두 가지 방식으로 구현 된 것을 보았고, (두 번째 방법으로 이전에 접근 한) 나 자신을 모두 한 후에는 상점이 조치에서 데이터를 수신하는 바보가되어야하며 쓰기의 비동기 처리는 액션 크리에이터. ( 비동기 읽기는 다르게 처리 될 수 있습니다 .) 내 경험상, 이것은 중요한 순서로 몇 가지 이점이 있습니다.

  1. 상점은 완전히 동기화됩니다. 이를 통해 상점 논리를 훨씬 더 쉽게 따르고 테스트하기가 쉽습니다. 특정 상태로 상점을 인스턴스화하고 조치를 보내고 상태가 예상대로 변경되었는지 확인하십시오. 또한 플럭스의 핵심 개념 중 하나는 계단식 디스패치를 ​​방지하고 한 번에 여러 디스패치를 ​​방지하는 것입니다. 상점에서 비동기 처리를 수행 할 때는 수행하기가 매우 어렵습니다.

  2. 모든 액션 파견은 액션 제작자에서 발생합니다. 상점에서 비동기 조작을 처리하고 상점의 조치 핸들러를 동기식으로 유지하려는 경우 (플럭스 단일 디스패치 보장을 확보하려면) 상점은 비동기에 대한 응답으로 추가 성공 및 실패 조치를 실행해야합니다. 가공. 이러한 발송을 액션 제작자에 넣는 대신 액션 제작자와 상점의 작업을 분리하는 데 도움이됩니다. 또한 작업을 어디에서 전달하는지 파악하기 위해 상점 논리를 파헤칠 필요가 없습니다. 이 경우 일반적인 비동기 동작은 다음과 같습니다 ( dispatch사용중인 플럭스의 풍미에 따라 호출 구문 변경 ).

    someActionCreator: function(userId) {
      // Dispatch an action now so that stores that want
      // to optimistically update their state can do so.
      dispatch("SOME_ACTION", {userId: userId});
    
      // This example uses promises, but you can use Node-style
      // callbacks or whatever you want for error handling.
      SomeDataAccessLayer.doSomething(userId)
      .then(function(newData) {
        // Stores that optimistically updated may not do anything
        // with a "SUCCESS" action, but you might e.g. stop showing
        // a loading indicator, etc.
        dispatch("SOME_ACTION_SUCCESS", {userId: userId, newData: newData});
      }, function(error) {
        // Stores can roll back by watching for the error case.
        dispatch("SOME_ACTION_FAIL", {userId: userId, error: error});
      });
    }
    

    여러 동작에 걸쳐 복제 될 수있는 논리는 별도의 모듈로 추출해야합니다. 이 예제에서 해당 모듈은 SomeDataAccessLayer실제 Ajax 요청 수행을 처리합니다.

  3. 더 적은 액션 제작자가 필요합니다. 이것은 큰 문제는 아니지만 가지고있는 것이 좋습니다. # 2에서 언급했듯이 상점에 동기 조치 디스패치 처리 (및 필요한 경우)가있는 경우 비동기 조치의 결과를 처리하기 위해 추가 조치를 실행해야합니다. 액션 제작자에서 디스패치를 ​​수행하면 단일 액션 제작자가 비동기 데이터 액세스 자체의 결과를 처리하여 세 가지 액션 유형을 모두 디스패치 할 수 있습니다.


나는이 질문을 Facebook의 개발자들에게 트윗했으며 Bill Fisher로부터 얻은 답변은 다음과 같습니다.

사용자와 UI의 상호 작용에 응답 할 때 액션 생성자 메서드에서 비동기 호출을 수행합니다.

그러나 시세 또는 사람이 아닌 다른 운전자가 있으면 상점에서 전화하는 것이 더 좋습니다.

중요한 것은 오류 / 성공 콜백에서 작업을 생성하여 데이터가 항상 작업에서 시작되도록하는 것입니다.


상점은 데이터 페치 및 상점의 데이터가 갱신되었음을 구성 요소에 알리는 것을 포함하여 모든 것을 수행해야합니다. 왜? 중요한 동작에 영향을 미치지 않으면 서 작업이 가볍고 일회용이며 교체 가능할 수 있기 때문입니다. 모든 중요한 행동과 기능은 상점에서 발생합니다. 이렇게하면 두 가지 매우 유사하지만 다른 동작으로 복사 될 동작의 중복을 방지 할 수 있습니다. 상점은 진실을 다루는 유일한 원천입니다.

모든 Flux 구현에서 Actions는 기본적으로 "anchor : clicked"라는 이벤트가 있지만 Flux에서는 AnchorActions.Clicked로 정의되는 것과 같이 기본적으로 이벤트 문자열이 객체로 바뀌는 것을 보았습니다. 그들은 심지어 "멍청한"것이어서 대부분의 구현에는 실제로 수신중인 상점에 이벤트를 디스패치하기 위해 별도의 Dispatcher 오브젝트가 있습니다.

개인적으로 필자는 별도의 Dispatcher 객체가없고 Action 객체가 디스패치 자체를 수행하는 Reflux의 Flux 구현을 좋아합니다.


편집 : Facebook의 Flux는 실제로 "액션 제작자"를 가져와 스마트 액션을 사용합니다. 또한 상점을 사용하여 페이로드를 준비합니다.

https://github.com/facebook/flux/blob/19a24975462234ddc583ad740354e115c20b881d/examples/flux-chat/js/actions/ChatMessageActionCreators.js#L27 (27 번 및 28 번 줄)

완료된 콜백은 이번에 페치 된 데이터를 페이로드로하여 새 조치를 트리거합니다.

https://github.com/facebook/flux/blob/19a24975462234ddc583ad740354e115c20b881d/examples/flux-chat/js/utils/ChatWebAPIUtils.js#L51

그래서 그것이 더 나은 해결책이라고 생각합니다.


나는 "멍청한"행동에 찬성하여 논쟁을 제시 할 것이다.

조치에서보기 데이터 수집에 대한 책임을 둠으로써 조치를보기의 데이터 요구 사항에 결합합니다.

In contrast, generic Actions, that declaratively describe the intent of the user, or some state transition in your application, allows any Store that responds to that Action to transform the intent, into state tailored specifically for the views subscribed to it.

This lends itself to more numerous, but smaller, more specialized Stores. I argue for this style because

  • this gives you more flexibility in how views consume Store data
  • "smart" Stores, specialized for the views that consume them, will be smaller and less coupled for complex apps, than "smart" Actions, on which potentially many views depend

The purpose of a Store is to provide data to views. The name "Action" suggests to me that its purpose is to describe a change in my Application.

Suppose you have to add a widget to an existing Dashboard view, which shows some fancy new aggregate data your backend team just rolled out.

With "smart" Actions, you might need to change your "refresh-dashboard" Action, to consume the new API. However, "Refreshing the dashboard" in an abstract sense has not changed. The data requirements of your views is what has changed.

With "dumb" Actions, you might add a new Store for the new widget to consume, and set it up so that when it receives the "refresh-dashboard" Action type, it sends a request for the new data, and exposes it to the new widget once it's ready. It makes sense to me that when the view layer needs more or different data, the things that I change are the sources of that data: Stores.


gaeron's flux-react-router-demo has a nice utility variation of the 'correct' approach.

An ActionCreator generates a promise from an external API service, and then passes the promise and three action constants to a dispatchAsync function in a proxy/extended Dispatcher. dispatchAsync will always dispatch the first action e.g. 'GET_EXTERNAL_DATA' and once the promise returns it will dispatch either 'GET_EXTERNAL_DATA_SUCCESS' or 'GET_EXTERNAL_DATA_ERROR'.


If you want one day to have a development environment comparable to what you see in Bret Victor's famous video Inventing on Principle, you should rather use dumb stores that are just a projection of actions/events inside a data structure, without any side effect. It would also help if your stores were actually member of the same global immutable data structure, like in Redux.

More explainations here: https://stackoverflow.com/a/31388262/82609

참고URL : https://stackoverflow.com/questions/25630611/should-flux-stores-or-actions-or-both-touch-external-services

반응형