2016-10-20 3 views
25

Недавно я начал переносить вещи из jQ в более структурированную структуру, являющуюся VueJS, и мне это нравится!Возвращение обещаний от действий Vuex

Концептуально, Vuex был для меня немного сменой парадигмы, но я уверен, что знаю, что все это сейчас, и полностью получить его! Но есть несколько небольших серых областей, в основном с точки зрения внедрения.

Этот я считаю хорошим по дизайну, но не знаю, противоречит ли он Vuex cycle однонаправленного потока данных.

В целом, считается ли это хорошей практикой возвращать объект (из-за) обещания? Я рассматриваю их как асинхронные обертки, состояния отказов и т. Д., Поэтому кажется, что это хорошо подходит для возврата обещания. Напротив, мутаторы просто меняют вещи и являются чистыми структурами в магазине/модуле.

ответ

64

actions в Vuex являются асинхронными. Единственный способ позволить вызывающей функции (инициатору действия) знать, что действие завершено, - это вернуть обещание и разрешить его позже.

Вот пример: myAction возвращает Promise, делает HTTP вызов и решает или отвергает Promise позже - все асинхронно

actions: { 
    myAction(context, data) { 
     return new Promise((resolve, reject) => { 
      // Do something here... lets say, a http call using vue-resource 
      this.$http("/api/something").then(response => { 
       // http success, call the mutator and change something in state 
       resolve(response); // Let the calling function know that http is done. You may send some data back 
      }, error => { 
       // http failed, let the calling function know that action did not work out 
       reject(error); 
      }) 
     }) 
    } 
} 

Теперь, когда ваш компонент Вью инициирует myAction, он получит этот объект Promise и может знать, удалось ли это или нет. Ниже приведен пример кода для компонента Вю:

export default { 
    mounted: function() { 
     // This component just got created. Lets fetch some data here using an action 
     this.$store.dispatch("myAction").then(response => { 
      console.log("Got some data, now lets show something in this component") 
     }, error => { 
      console.error("Got nothing from server. Prompt user to check internet connection and try again") 
     }) 
    } 
} 

Как вы можете видеть выше, это очень полезно для actions вернуть Promise. В противном случае инициатор действия не сможет узнать, что происходит, и когда ситуация достаточно стабильна, чтобы показать что-то в пользовательском интерфейсе.

И последнее примечание относительно mutators - как вы правильно указали, они синхронны. Они меняют вещи в state, и их обычно называют от actions. Не нужно смешивать Promises с mutators, так как actions ручка эта часть.

Редактировать: Мои взгляды на цикл Vuex из однонаправленного потока данных:

Если доступ к данным как this.$store.state["your data key"] в ваших компонентах, то поток данных является однонаправленным.

Обетование от действия только для того, чтобы компонент знал, что действие завершено.

Компонент может использовать данные из функции разрешения обещаний в приведенном выше примере (не однонаправленный, поэтому не рекомендуется), либо непосредственно из $store.state["your data key"], который является однонаправленным и следует за жизненным циклом данных vuex.

Вышеупомянутый абзац предполагает, что ваш мутатор использует Vue.set(state, "your data key", http_data), как только HTTP-запрос будет завершен в вашем действии.

+0

«Как вы можете видеть выше, очень полезно, чтобы действия возвращали обещание. В противном случае инициатор действия не может знать, что происходит, и когда все достаточно стабильно, чтобы что-то показывать в пользовательском интерфейсе». ИМО, этого не хватает в Vuex.Инициатор действия не должен * знать, что происходит. Действие должно мутировать состояние, когда данные возвращаются из асинхронного события, и компонент должен реагировать на это изменение этапа, основанное на состоянии хранилища Vuex, а не на Promise. – ceejayoz

+1

@ceejayoz Согласовано, государство должно быть единственным источником истины для всех объектов данных. Но обещание - это единственный способ связаться с инициатором акции. Например, если вы хотите показать кнопку «Попробовать еще раз» после отказа HTTP, эта информация не может войти в состояние, но может быть передана только через «Promise.reject()». – Mani

+0

Это легко обрабатывается в магазине Vuex. Само действие может запускать «failed» мутатор, который устанавливает 'state.foo.failed = true', который компонент может обрабатывать. Нет необходимости в том, чтобы обещание было передано компоненту для этого, и в качестве бонуса все, что угодно * else *, которое хочет реагировать на один и тот же отказ, может сделать это и в магазине. – ceejayoz