Удаленный элемент существует после удаления до обновления — VueJS

#javascript #vue.js #async-await #axios

#javascript #vue.js #асинхронный -ожидание #axios

Вопрос:

Я пытаюсь создать простое приложение, в котором у меня есть список поставщиков, и я хочу добавить / удалить их … одна и та же проблема для обоих случаев

когда я пытаюсь удалить элемент или и когда я пытаюсь добавить элемент (поставщик)

Вот ситуация:

Provider.vue: * загрузка поставщиков из и API (просто так)

 <template lang="html">
 <div class="container">
   <h1 class="h2">{{ $t('default.titles.providers') }}</h1>
     <button class="btn btn-success my-3 float-right" @click="addProvider">{{ $t('default.buttons.add') }}</button>
     <template v-if="showError">
       <div class="clearfix"></div>
       <tw-loading-error :message="this.error"></tw-loading-error>
     </template>
     <template v-else>
       <table class="table table-hover table-sm">
         <thead>
           <tr>
             <th scope="col">#</th>
             <th scope="col">{{ $t('default.provider.name') }}</th>
             <th scope="col"></th>
             <th scope="col"></th>
             <th scope="col"></th>
           </tr>
         </thead>
         <tbody>
           <tr v-for="(provider, index) in providerList" :key="index">
             <th scope="row">{{index 1}}</th>
             <td>{{provider.provider_name}}</td>
             <td :title="$t('default.buttons.edit')">
               <router-link :to="{ name: 'edit-provider', params: { provider } }">
                 <Edit2Icon
                   class="pointer">
                 </Edit2Icon>
              </router-link>
             </td>
             <td :title="$t('default.buttons.delete')">
               <router-link class="delete" :to="{ name: 'delete-provider', params: { provider } }">
                   <DeleteIcon
                     class="pointer">
                   </DeleteIcon>
               </router-link>
             </td>
             <td :title="$t('default.buttons.add-client')">
               <router-link class="edit" :to="{ name: 'add-provider-user',
                                                params: {
                                                  provider_id: provider.id_provider,
                                                  provider_name: provider.provider_name
                                               }}">
                 <UserPlusIcon class="pointer"></UserPlusIcon>
               </router-link>
             </td>
           </tr>
         </tbody>
       </table>
     </template>
 </div>
</template>

<script>
  import ProviderService from './../../../services/provider.service'
  import { Edit2Icon, DeleteIcon, UserPlusIcon } from 'vue-feather-icons'
  import LoadingError from './../../shared/alerts/LoadingError.vue'

  export default {
    name: "Provider",
    data() {
      return {
        providerList: [],
        error: '501: cannot load the providers :(',
        showError: false
      }
    },
    components: {
      'tw-loading-error': LoadingError,
      Edit2Icon, DeleteIcon, UserPlusIcon
    },
    methods: {
      getProviders() {
        ProviderService.getProviders().then(
          response => {
            this.providerList = response.data
          },
          error => {
            this.showError = true
            this.error = error
          }
        )
      },
      addProvider() {
        this.$router.push({name: "add-provider"})
      },
    },
    mounted() {
      this.getProviders();
    }
  }
</script>

<style lang="css" scoped>
.pointer {
  cursor: pointer;
}
.delete {
  color: red;
}
</style>
  

provider.service.js : * очень просто .. Я либо получаю весь поставщик, либо удаляю поставщика

 import axios from '../axios/axios-conf'
import authHeader from './auth-header';

class ProviderService {
  async getProviders() {
    const response = await axios.get('/providers', { headers: authHeader() })
    return response
  }

  async deleteProvider(id){
     try {
       return await axios.delete('/provider/delete/' id)
     } catch (error) {
       return error
     }
  }
}

 export default new ProviderService()
  

DeleteProvider.vue: * вот виновник

 <template lang="html">
 <div class="container">
   <h1 class="h2">{{$t('default.titles.delete')}} {{provider.name}}?</h1>
      <div class="container">
        <button class="btn btn-danger" @click="deleteProvider(provider.id)">{{$t('default.buttons.yes')}}</button>
        <button class="btn btn-sm btn-secondary" @click="goBack">{{$t('default.buttons.no')}}</button>
      </div>
 </div>
</template>

<script>
//  import axios from './../../../axios/axios-conf'
  import ProviderService from './../../../services/provider.service'

  export default {
    name: "DeleteProvider",
    data() {
      return {
        provider: {
          id: null,
          name: null
        }
      }
    },
    components: {
    },
    methods: {
      async deleteProvider(id){
        let c = confirm("Do you really want to delete it? You will not be able to restore this data again!")
        if(c){
          this.delete(id)
              .then(success => {
                return success
              })
              .catch(error => {
                return error
              })
          this.goBack()
        }
      },
      async delete(id){
        let response = await ProviderService.deleteProvider(id)
        return response
      },
      checkParams(){
          if(JSON.stringify(this.$route.params) === '{}'){
            this.goBack()
          }
      },
      goBack(){
        this.$router.push({ name: 'provider'})
      }
    },
    mounted() {
      this.provider.name = this.$route.params.provider.provider_name
      this.provider.id = this.$route.params.provider.id_provider
    },
    created() {
      this.checkParams()
    }
  }
</script>

<style lang="css" scoped>
.pointer{
  cursor: pointer
}
</style>
  

API-интерфейсы работают безупречно .. они делают то, что ожидается.. проблема возникает, когда я пытаюсь удалить провайдера, VueJS перенаправляет меня (маршрутизатор) так быстро в список провайдеров, что элемент не исчезает (тот, который удален). Только после того, как я обновлю страницу (либо через F5, либо перейду на другую страницу и обратно, чтобы отобразить ее снова), она проецируется.

Итак, дело в том, что он успешно удален, но страница не ждет или удаление не проецирует его сразу.

Что я делаю не так? У меня есть async / await в моем коде для всех функций (отчаянная ситуация требует отчаянных мер: D)

PS: стоит упомянуть: это происходит только время от времени .. иногда это работает нормально (поэтому элемент не отображается .. иногда мне приходится обновлять страницу)

Спасибо

Ответ №1:

this.goBack() Неправильно ожидает завершения асинхронной функции. this.delete(id) Строка ниже и this.goBack() строки выполняются параллельно, поскольку delete это асинхронный вызов.

Кроме того, вы также можете использовать try...catch блок вместо цепочки обещаний. Посмотрите на мои изменения ниже:

 async deleteProvider(id){
        let c = confirm("Do you really want to delete it? You will not be able to restore this data again!")
        if(c){
          try{
             const success = await this.delete(id)
             return success;
           } catch(error){
             return error;
           } finally {
              this.goBack(); // If you want to go back only on success, move this line inside the try block before the `return`.
           }
        }
      }