Vuex क्रियाओं से वापसी का वादा


130

मैंने हाल ही में jQ से चीजों को एक अधिक संरचित ढांचे में स्थानांतरित करना शुरू किया है, जो कि VueJS है, और मुझे यह पसंद है!

वैचारिक रूप से, Vuex मेरे लिए एक प्रतिमान बदलाव का एक सा रहा है, लेकिन मुझे विश्वास है कि मुझे पता है कि अब इसके बारे में क्या है, और पूरी तरह से इसे प्राप्त करें! लेकिन वहाँ कुछ ग्रे क्षेत्रों मौजूद हैं, ज्यादातर एक कार्यान्वयन के दृष्टिकोण से।

यह मुझे ऐसा लगता है कि डिजाइन अच्छा है, लेकिन यह नहीं पता है कि यह यूआई -दिशात्मक डेटा प्रवाह के Vuex चक्र का खंडन करता है ।

मूल रूप से, क्या किसी कार्रवाई से एक वादा (जैसे) वस्तु वापस करने के लिए अच्छा अभ्यास माना जाता है? मैं इनको async रैपर के रूप में मानता हूं, विफलता की अवस्थाओं और पसंद के साथ, इसलिए यह वादा वापस करने के लिए एक अच्छा फिट की तरह लगता है। इसके विपरीत म्यूटेटर सिर्फ चीजें बदलते हैं, और एक स्टोर / मॉड्यूल के भीतर शुद्ध संरचनाएं हैं।

जवाबों:


255

actionsVuex में अतुल्यकालिक हैं। कॉलिंग फ़ंक्शन (कार्रवाई के आरंभकर्ता) को यह बताने का एकमात्र तरीका है कि एक कार्रवाई पूरी हो गई है - एक वादा वापस करके और बाद में हल करके।

यहाँ एक उदाहरण है: 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);
            })
        })
    }
}

अब, जब आपका Vue घटक आरंभ होता है myAction, तो उसे यह वादा वस्तु मिल जाएगी और पता चल सकता है कि यह सफल हुआ या नहीं। यहाँ Vue घटक के लिए कुछ नमूना कोड है:

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 कॉल आपके एक्शन में पूरी हो जाने के बाद उपरोक्त पैराग्राफ आपके म्यूटेटर का उपयोग करता है।


4
"जैसा कि आप ऊपर देख सकते हैं, क्रियाओं के लिए एक वादा वापस करने के लिए यह बहुत फायदेमंद है। अन्यथा कार्रवाई सर्जक के लिए यह जानने का कोई तरीका नहीं है कि क्या हो रहा है और जब उपयोगकर्ता इंटरफ़ेस पर कुछ दिखाने के लिए चीजें स्थिर हैं।" IMO, यह Vuex की बात याद आ रही है। कार्रवाई आरंभकर्ता को यह जानने की आवश्यकता नहीं है कि क्या हो रहा है। जब डेटा एसिंक्रोनस इवेंट से वापस आता है, तो कार्रवाई को स्थिति को बदलना चाहिए, और घटक को Vuex स्टोर की स्थिति के आधार पर उस चरण परिवर्तन का जवाब देना चाहिए, न कि एक वादा।
ceejayoz

1
@ceejayoz सहमत, राज्य को सभी डेटा ऑब्जेक्ट के लिए सत्य का एकल स्रोत होना चाहिए। लेकिन एक्शन सर्जक को वापस संवाद करने का एकमात्र तरीका वादा है। उदाहरण के लिए, यदि आप http विफलता के बाद "पुनः प्रयास करें" बटन दिखाना चाहते हैं, तो वह जानकारी राज्य में नहीं जा सकती है, लेकिन केवल एक के माध्यम से वापस संचारित किया जा सकता है Promise.reject()
मणि

1
जिसे आसानी से Vuex स्टोर के भीतर संभाला जा सकता है। कार्रवाई खुद को failedसेट करने वाले म्यूटेटर को आग लगा सकती है state.foo.failed = true, जिसे घटक संभाल सकता है। वादा करने के लिए कोई ज़रूरत नहीं है कि के लिए घटक को पास करने की है, और एक बोनस के रूप में, कुछ भी नहीं तो एक ही विफलता के लिए प्रतिक्रिया करने के लिए चाहता है वह भी दुकान से ऐसा कर सकते हैं।
सिजयोज़

4
@ceejayoz की जाँच लिखना क्रिया - में डॉक्स (पिछले अनुभाग) vuex.vuejs.org/en/actions.html - कार्यों अतुल्यकालिक रहे हैं और इसलिए एक वादा लौटने एक अच्छा विचार के रूप में उन डॉक्स में कहा गया है। शायद ऊपर $ http मामले में नहीं है, लेकिन किसी अन्य मामले में हमें यह जानना पड़ सकता है कि कोई कार्रवाई कब पूरी होगी।
मणि

6
@DanielPark हां, यह "निर्भर करता है" परिदृश्य और व्यक्तिगत डेवलपर प्राथमिकताओं पर। मेरे मामले में, मैं {isLoading:true}अपने राज्य की तरह मध्यवर्ती मूल्यों से बचना चाहता था , और इसलिए वादों का सहारा लिया। आपकी प्राथमिकताएँ भिन्न हो सकती हैं। दिन के अंत में, हमारा उद्देश्य अव्यवस्था मुक्त और बनाए रखने योग्य कोड लिखना है। क्या वादे उस उद्देश्य को प्राप्त करते हैं, या vuex राज्य - निर्णय लेने के लिए व्यक्तिगत डेवलपर्स और टीमों पर छोड़ दिया जाता है।
मणि

41

बस एक बंद विषय पर जानकारी के लिए: आपको एक वादा करने की ज़रूरत नहीं है, axios एक ही रिटर्न:

Ref: https://forum.vuejs.org/t/how-to-resolve-a-promise-object-in-a-vuex-action-and-redirect-to-another-route/182544/4

उदाहरण:

    export const loginForm = ({ commit }, data) => {
      return axios
        .post('http://localhost:8000/api/login', data)
        .then((response) => {
          commit('logUserIn', response.data);
        })
        .catch((error) => {
          commit('unAuthorisedUser', { error:error.response.data });
        })
    }

एक और उदाहरण:

    addEmployee({ commit, state }) {       
      return insertEmployee(state.employee)
        .then(result => {
          commit('setEmployee', result.data);
          return result.data; // resolve 
        })
        .catch(err => {           
          throw err.response.data; // reject
        })
    }

एक और उदाहरण async-wait के साथ

    async getUser({ commit }) {
        try {
            const currentUser = await axios.get('/user/current')
            commit('setUser', currentUser)
            return currentUser
        } catch (err) {
            commit('setUser', null)
            throw 'Unable to fetch current user'
        }
    },

क्या अंतिम उदाहरण निरर्थक नहीं होना चाहिए क्योंकि अक्षतंतु क्रियाएं डिफ़ॉल्ट रूप से पहले से ही अतुल्यकालिक हैं?
nonNumericalFloat

9

क्रिया

ADD_PRODUCT : (context,product) => {
  return Axios.post(uri, product).then((response) => {
    if (response.status === 'success') {  
      context.commit('SET_PRODUCT',response.data.data)
    }
    return response.data
  });
});

अंग

this.$store.dispatch('ADD_PRODUCT',data).then((res) => {
  if (res.status === 'success') {
    // write your success actions here....
  } else {
     // write your error actions here...
  }
})

2
यह घटक में अपरिभाषित प्रतिक्रिया नहीं कर रहा है
नंद लाल

1
मुझे लगता है कि आप ADD_PRODUCT फ़ंक्शन में वापसी जोड़ना भूल गए हैं
भास्करराव गुम्मिदि

लोअरकेस "ए" "एक्सियोस" में होना चाहिए।
बीपी

मैंने एक्सोइस को कास्ट के रूप में लिया जो कि 'एक्सियोस' से आयात हो रहा है
भास्करराव गुम्मिदी

0

टी एल: डॉ; आवश्यक होने पर ही आप से वादे वापस करते हैं, लेकिन DRY उसी क्रियाओं का पीछा करते हैं।

एक लंबे समय के लिए मैं यह भी है कि लौटने की कार्रवाई यूनी-दिशात्मक डेटा प्रवाह के Vuex चक्र का खंडन करती है।

लेकिन, ऐसे मामले हैं जहां आपके कार्यों से एक वादा वापस करना "आवश्यक" हो सकता है।

ऐसी स्थिति की कल्पना करें जहां 2 अलग-अलग घटकों से एक क्रिया को ट्रिगर किया जा सकता है, और प्रत्येक विफलता मामले को अलग तरीके से संभालता है। उस मामले में, किसी को स्टोर में अलग-अलग झंडे सेट करने के लिए एक पैरामीटर के रूप में कॉलर घटक को पास करना होगा।

गूंगा उदाहरण

वह पृष्ठ जहाँ उपयोगकर्ता उपयोगकर्ता नामबार में और / प्रोफ़ाइल पृष्ठ (जिसमें नावबार होता है) को संपादित कर सकता है। दोनों एक क्रिया "उपयोगकर्ता नाम बदलें" को ट्रिगर करते हैं, जो अतुल्यकालिक है। यदि वादा विफल हो जाता है, तो पृष्ठ को केवल उस घटक में एक त्रुटि प्रदर्शित करनी चाहिए, जिस उपयोगकर्ता को उपयोगकर्ता नाम बदलने की कोशिश की गई थी।

बेशक यह एक गूंगा उदाहरण है, लेकिन मुझे इस मुद्दे को बिना कोड डुप्लिकेट किए और 2 अलग-अलग कार्यों में एक ही कॉल करने का कोई तरीका नहीं दिखता है।


-1

actions.js

const axios = require('axios');
const types = require('./types');

export const actions = {
  GET_CONTENT({commit}){
    axios.get(`${URL}`)
      .then(doc =>{
        const content = doc.data;
        commit(types.SET_CONTENT , content);
        setTimeout(() =>{
          commit(types.IS_LOADING , false);
        } , 1000);
      }).catch(err =>{
        console.log(err);
    });
  },
}

home.vue

<script>
  import {value , onCreated} from "vue-function-api";
  import {useState, useStore} from "@u3u/vue-hooks";

  export default {
    name: 'home',

    setup(){
      const store = useStore();
      const state = {
        ...useState(["content" , "isLoading"])
      };
      onCreated(() =>{
        store.value.dispatch("GET_CONTENT" );
      });

      return{
        ...state,
      }
    }
  };
</script>
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.