Mobx / React和异步动画

时间:2018-04-17 10:15:52

标签: reactjs mobx mobx-react

我有一个事件发射器(EE),当'下一个''函数被调用。

我创建了一个商店,用于监听此EE发出的事件,并将事件名称存储在一个可观察的内容中。

一堆React组件对这个可观察对象做出异步反应(动画)。

我想要的: 鉴于当前的事件,我希望商店电话'下一个''只有当对该特定事件感兴趣的所有组件都完成了他们的动画时才在EE上。

mob-x的方法是什么?

编辑:这里是商店的代码

import {observable, autorun} from 'mobx'
    import Solitaire from 'cgk-solitaire'
    import AnimationController from './AnimationController'

    export default class AppStore {
      constructor ({debug = false}) {
        this._debug = debug
        if (this._debug) {
          window.appStore = this
        }
        this._solitaire = new Solitaire({
          game: Solitaire.TRIS
        })

        this._addListeners()

        this.animationController = new AnimationController()

        this.selectedCard = observable.box()
        this.selectedSlot = observable.box()

        this.currentEvent = observable.box()
        this.currentCallback = null
        this.currentStatus = this._solitaire._status // TODO: refactor this

        // Move Reactive Handling
        autorun(() => {
          const card = this.selectedCard.get()
          const slotId = this.selectedSlot.get()
          if (this.currentEvent.get() === 'PLAY' && !!card && Number.isInteger(slotId)) {
            const tableX = slotId < 4 ? 0 : 1
            const tableY = slotId % 4
            const move = this._solitaire.move({card, tableX, tableY})
            this.next(move)
          }
        })
      }

      begin () {
        this._solitaire.begin()
      }

      // Select Card only if the last in hand
      setSelectedCard (card) {
        if (card.id === this.currentStatus.hand.last.id) {
          this.selectedCard.set(card)
        }
      }

      // Select Slot only if a card is selected
      setSelectedSlot (slotId) {
        if (this.selectedCard.get()) {
          this.selectedSlot.set(slotId)
        }
      }

      drawMore () {
        const action = this._action(Solitaire.action.ACT_DRAW_MORE)
        this.next(action)
      }

      setAutoplay (bool) {
        this._solitaire.command(Solitaire.command.CMD_AUTOPLAY, {bool: bool})
      }

      shuffle () {
        this._solitaire._status.shuffleDeck()
      }

      next (payload) {
        if (this.currentCallback) {
          this.currentCallback(payload)
          this._reset()
        }
      }

      _reset () {
        this.selectedCard.set()
        this.selectedSlot.set()
        this.currentCallback = null
      }

      _addListeners () {
        Object.keys(Solitaire.event).forEach(event => {
          this._solitaire.on(event, (status, callback) => {
            this._debug && console.log('*** ' + event + ' ***')
            this.currentStatus = status
            this.currentCallback = callback
            this.currentEvent.set(event)
          })
        })
      }

      _move (data) {
        return this._solitaire.move(data)
      }

      _action (action) {
        return this._solitaire.action(action)
      }

    }

1 个答案:

答案 0 :(得分:0)

事件发射器与mobx无关。

这是你可以做的:

  1. 让所有应该等待的听众回复承诺。
  2. 等待事件发射器中的所有承诺(反模式的位,但是想知道听众何时完成)
  3. 设置mobx状态,表示已完成某事(例如使用subproperty
  4. 在事件监听器

    上返回promise
     function trigger(){
       var results = this.listeners.map(listener=> listener());
       var onlyPromises = results.filter(x=> x instanceof Promise);
       var onAllCompleted = Promise.all(onlyPromises);
    
       // or:
       onAllCompleted.then(()=> {
          mobxStore.isFinished = true;
       });
       // or: use mobx-utils
       mobxStore.animationState = mobxUtils.fromPromise(onAllCompleted);
     }
    

    等待承诺

    事件发射器:

     func customizeButtonFont(fullText: String, mainText: String, creditsText: String, button: UIButton) {
            let fontBig = UIFont(name:"SFUIDisplay-Medium", size: 16.0)
            let fontSmall = UIFont(name:"SFUIDisplay-Light", size: 14.0)
            let attributedString = NSMutableAttributedString(string: fullText, attributes: nil)
    
            let bigRange = (attributedString.string as NSString).range(of: mainText)
            let creditsRange = (attributedString.string as NSString).range(of: creditsText)
            attributedString.setAttributes([NSAttributedStringKey.font: fontBig, NSAttributedStringKey.foregroundColor: UIColor.white], range: bigRange)
            attributedString.setAttributes([NSAttributedStringKey.font: fontSmall, NSAttributedStringKey.foregroundColor: UIColor.white], range: creditsRange)
    
            button.setAttributedTitle(attributedString, for: .normal)
        }