Async snotify axios in vuejs project

176
27 июля 2018, 14:50

Пытаюсь разобраться с axios, обёрнутым в snotify в своём проекте на VueJS. Нашёл пример того, как можно поместить одно в другое, но возникает проблема - как в случае успеха или ошибки выполнить тот или иной код. Ведь внутри Promise и внутри axios я не могу обратиться ко внешним функциям vue. Как быть?

Ниже код запроса axios к api axios.post('samples',this.sample) перед этим обернутый в Promise для того, чтобы snotify (показывает сообщения пользователяю) во время выполнения запроса анимировал сообщение, что идёт запрос. Когда запрос завершён успешно, внутри axios вызывается resolve - отображается сообщение об успехе. Если ошибка, то она отлавливается и выводится сообщение, описанное в reject.

Мне же нужно не просто показать сообщение об успехе или ошибке пользователю, мне помимо всего прочего нужно произвести кое-какие действия в том и другом случае. Например, если запрос состоялся, то выводится сообщение об успехе и вызывается функция this.test(); Однако я получаю ошибку - функция не вызывается.

<template>
    <button type="button" class="btn btn-primary" @click="createSample">
        Добавить образец
    </button>      
</template>

Скрипт:

  export default {
    name: "sample",
    data() { return { sample: {} } },
    methods: {
      test() {
        console.log('it works!');
      },
      createSample() {
        this.$snotify.async('Called with promise', 'Success async', () => {
          return new Promise((resolve, reject) => {
            return axios.post('samples', this.sample)
              .then(function(success) {
                success = success.data;
                console.log(success); //Ответ сервера отображается. В БД данные есть.
                this.test(); //Ошибка. Не может выполнить функцию. Вызывается reject
                resolve({
                  title: 'Успех',
                  body: 'Новый образец добавлен',
                  config: { closeOnClick: true }
                });
              })
              .catch(function(error) {
                reject({
                  title: 'Ошибка',
                  body: 'Что-то пошло не так',
                  config: { closeOnClick: true }
                })
              });
          });
        });
      },
    }
  }

Рабочий пример на jsfiddle прилагается.

Answer 1

Вам просто нужно пробросить this внутрь функции промиса. Ваш HTML остается без изменений, таким как и был ранее:

<div id="app">
    <button type="button" class="btn btn-primary" @click="createSample">
            Добавить образец
        </button>   
   <vue-snotify></vue-snotify>
</div>

Вот JS немного поменяется (за основу взят ваш код из JsFiddle):

const app = new Vue({
  el: '#app',
  methods: {
    test() {
      console.log('it works!');
    },
    createSample() {
      this.$snotify.async('Called with promise', 'Success async', () => {
        return new Promise((resolve, reject) => {
          return axios.get('https://jsonplaceholder.typicode.com/users')
            .then(function(success) {
              success = success.data;
              console.log(success); // Ответ сервера
              this.test(); // После того, как сделали bind(this) - ошибки не будет
              resolve({
                title: 'Успех',
                body: 'Новый образец добавлен',
                config: {
                  closeOnClick: true
                }
              });
            }.bind(this)) // вот тут мы пробросили this внутрь
            .catch(function(error) {
              reject({
                title: 'Ошибка',
                body: 'Что-то пошло не так',
                config: {
                  closeOnClick: true
                }
              })
            });
        });
      });
    },
  }
});

Все решилось с помощью добавления .bind(this) к функции, которая выполняется внутри then. Если не выполнить bind, то this внутри функции - это всего лишь область функции.

Также, есть еще более простой вариант - это стрелочная функция. Стрелочные функции при создании привязываются к текущему значению this. Поэтому код станет немного современнее и проще (на примере then, где вызывается функция test):

.then((success) => {
    success = success.data;
    console.log(success); // Ответ сервера 
    this.test(); // Можем выполнить эту функцию
    resolve({
        title: 'Успех',
        body: 'Новый образец добавлен',
        config: {
            closeOnClick: true
        }
    });
})
READ ALSO
Функция (Проверка на пустоту)

Функция (Проверка на пустоту)

Начинающий в js прошу сильно не пинать) функция по клику создает заголовок h4, так же вместе с заголовком создается ссылка с кнопкой удаления...

192
Как считать время в input с datetimepicker

Как считать время в input с datetimepicker

Имеется input с подключенным bootstrap datetimepickerТакже задается defaultDate в котором дата задается с помощью moment

168
Как удалить атрибут на JS Pure?

Как удалить атрибут на JS Pure?

Вот так выгрядит код на jQuery

167
Ошибка в связи двух select

Ошибка в связи двух select

Есть два списка и в каждом одинаковое количество optionМоя задача сделать так, чтобы на выбор и-того элемент одного списка выбирался и-тый элемент...

189