使用Vue.js进行异步/等待的axios调用

16

我在我的Vue.js应用程序中设置一个this的值时遇到了一些麻烦。我认为我可能没有正确理解异步axios调用,或者不知道在Vue.js中如何使用异步。

我有以下三种方法:

updateAvailability(availability) {
    if (availability == true) {
        this.showYourDetails();
    } else {
        this.showBookingDetails();
    }
},
checkAvailability: async function(event) {
    event.preventDefault();
    const availability = await this.handleAvailabilityRequest(event);
    this.loading = true;
    console.log(availability); //This evaluates to undefined
    const availabilityUpdate = await this.updateAvailability(availability);
    this.loading = false;
},
handleAvailabilityRequest: async function(event) {
    event.preventDefault();
    let valid = this.validateFieldsForAvailabilityRequest(); //Ignore this for this particular question, assume valid is always true

    if (valid) { // This is true
        let config = {
            headers: {
                "X-CSRFToken": this.csrfToken,
                "Content-Type": 'application/x-www-form-urlencoded',
            }
        }

        let formData = new FormData();
        let reservationTime = this.reservationHourSelected + ':' + this.reservationMinuteSelected;

        formData.set('type', 'availability_request');
        formData.set('session_name', this.sessionName);
        formData.set('reservation_party_size', this.reservationPartySize);
        formData.set('reservation_date', this.reservationDate);
        formData.set('reservation_time', reservationTime);

        await axios.post('{{ request_absolute_uri }}', formData, config).then(function(response) {
            this.availabilityMessage = response.data.message;
        }).catch(function(error) {
            this.availabilityMessage = false;
            console.log(error);
        });
    }
    return this.availabilityMessage;
}

我的response.data.message从框架传回时是True/true,但似乎我没有从await this.handleAvailabilityRequest()函数中返回任何内容? 日志记录显示我的请求已成功发送到服务器并返回json响应上下文中的message = true。

所以, 我猜... 帮帮我!除了等待承诺的问题之外,我完全不知道为什么它不起作用...


你应该在这里使用箭头函数,否则你将无法获得正确的上下文。 - Vivick
Vivick是正确的,或者在你的错误回调函数末尾添加.bind(this) - Thoomas
既然你正在更新“this” availabilityMessage,我不认为在请求中返回它有任何意义。相反,下一步调用时检查this.availabilityMessage而不是availability。 - IamLasse
你同时混合了async/await和标准Promise,这可能会导致问题。最好只使用其中之一。我更喜欢在这些情况下使用async/await,但我也发现有时必须在等待的调用上使用Promise.all。 - IamLasse
2个回答

26

问题在这里:

await axios.post('{{ request_absolute_uri }}', formData, config).then(function(response){
  this.availabilityMessage = response.data.message;
}).catch(function (error) {
  this.availabilityMessage = false;
  console.log(error);
});

由于您正在使用完整的function,因此.then内部的this不是指向实例化的对象。改用箭头函数,这样this就会继承外部作用域:

await axios.post('{{ request_absolute_uri }}', formData, config)
.then((response) => {
  this.availabilityMessage = response.data.message;
}).catch((error) => {
  this.availabilityMessage = false;
  console.log(error);
});

1
这个很顺利地运行了。经过一些修改,外部作用域现在正在改变。只是出于兴趣,为什么会这样工作呢? - GCien
1
使用标准函数,任何函数内部的 this 都是该函数的 调用上下文 - 在您的原始代码中,这是 .post 返回的 Promise。而对于箭头函数,this 总是从外部作用域 继承,而不是依赖于箭头函数的调用上下文。 - CertainPerformance
3
如果你必须使用 function(),你可以通过 bind 方法将父级上下文(this)绑定到它上面。function() {}.bind(this) - Niek van der Maaden
你也可以在方法的开头使用老式的 let vm = this(或者如果需要极端情况下使用 var),并将其用于代替 this - Christian Bonato
如果使用 Then,仍然需要使用 await 吗? - Muhammad
@Muhammad 没有必要,但是与await结合使用可以实现所需的控制流程。(另一种选择是将后续所有内容嵌套在另一个.then中) - CertainPerformance

24

如果你使用async await,为什么还要使用promises模式呢?这样可以避免使用回调和this绑定丢失。

你可以像这样做:

handleAvailabilityRequest: async function (event) {
  event.preventDefault();
    ...

  try{
   let response =  await axios.post('{{ request_absolute_uri }}', formData, config)
      this.availabilityMessage = response.data.message;
  }catch(error) {
      this.availabilityMessage = false;
      console.log(error);
    };
  }
  return this.availabilityMessage;
}

使用 async/await 时,可以使用 try/catch 块来处理错误。


5
为什么在使用async/await时要使用promises?因为async函数返回一个promise,而await只能等待返回promise的函数。 - Quentin
1
axios确实会返回一个Promise。 - Vamsi Krishna
3
@Quentin,我们可以等待承诺得到解决并返回“response”。 - Vamsi Krishna
1
"finally" 是一个很好的清理 try catch 后续工作的方式。我经常使用它。 - IamLasse
1
这是我个人认为更好的答案。async/await是一个改变游戏规则的技术。避免使用那些绑定了Promise的函数,无疑可以让代码更加清晰。 - Nick Cipollina

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接