记一次Promise数据传递中的return坑

熟悉的 Promise 语法的都知道, Promise 的 then 、 catch 方法可以使用链式操作,在 then 的链式操作中,前面操作返回的值是可以被后面的操作所获取到的。

目录
  1. 前言
  2. 分析
  3. 代码
  4. 总结

记一次 Promise 数据传递中的 return 坑

前言#

熟悉的 Promise 语法的都知道,Promisethencatch方法可以使用链式操作,在then的链式操作中,前面操作返回的值是可以被后面的操作所获取到的。

如下代码:

const result = new Promise(// ...)
result
  .then(data => {
    console.log(data)
    // ....
    return data.a
  })
  .then(data => {
    console.log(data) // data.a
  })

最近在写 Vue 代码时,写了一个 Promise 的封装函数,专门用来处理 Axios 请求过来的数据。

// api/index.js
const handleRequest = request => {
  return new Promise((resolve, reject) => {
    request
      .then(res => {
      // ...
    })
      .catch(err => {
      // ...
    })
  })
}
 
export default {
  getData() {
    return handleRequest(axios.get(// ...))
  }
}

分析#

因为有用Vuex来管理数据,为了方便,我把关于数据请求的操作全部放在 store 的 actions 中。

然后 Axios 请求过来的数据,分别需要有下面三种处理情况:

  1. 把一些数据保存到 store 里,这些数据后面 Vue 组件会用到。
  2. 不需要把数据到 store 中(后端只操作了数据库的数据,传给前端一个成功状态或者失败消息即可),但是有时候前端需要根据请求过来的状态(status)和消息(msg)的不同,作出一些不同的操作,比如提醒、跳转页面等。当然,有时候也会完全不用操作,比如账户登出。
  3. 既要保存数据,又要传出相应的状态或者消息提示给 Vue 组件进行实时交互操作。

代码#

  • 对于第一种情况,非常简单,把数据commit到 mutations 的函数方法中,然后再保存到 state 中就行了。后面 Vue 组件就可以通过mapGetters或者mapState语法糖调用这些数据。
// actions.js
import api from '../api'
 
export const getData =({commit}, params=> {
  api.getData(params)  // 这里可以不需要使用 return,因为没有后续操作了
    .then(data => {
    	commit(//...)
     })
}
  • 对于第二种情况,更简单,直接返回api.js的函数就行了,然后 Vue 组件通过mapActions语法糖就可以使用 actions 的函数。
// actions.js
import api from '../api'
 
export const getData =()=> {
  return api.getData()  // 如果没有后续操作可以不用写 return
}
  • 对于第三种情况,则比前面两种情况稍微复杂点,需要把两种方法结合起来。一开始我是重新封装一个 Promise 函数传递出去的。
// actions.js
import api from '../api'
 
export const getData =({commit}, params=> {
  return new Promise((resolve, reject) => {
    api.getData(params)
      .then(data => {
      // ...
      commit(//...)
        resolve(data)
        })
        .catch(err => {
        // ...
        reject(err)
      })
    })
}

但是后面想起来,promise 的then方法是可以一层一层传递参数的,只需要把数据保存到 store 后,再把数据往下传就可以了,这样代码更少,更简单。于是修改了上面的代码:

// actions.js
import api from '../api'
 
export const getData =({commit}, params=> {
  api.getData(params)
    .then(data => {
    // ...
    commit(//...)
      return data
    })
}

但是发现 Vue 组件调用这个函数后,用then()完全获取不了return出来的data数据,获得的是undefined。这不科学啊,百思不得其解!!!

之后才发现:原来这里有一个,我是不是少写了什么?没错,就是return,一直以来我能不写 return 就不写 return 的,这次终于掉了。

正确的代码是这样的:

// actions.js
import api from '../api'
 
export const getData =({commit}, params=> {
  return api.getData(params)  // 记得写上 return
    .then(data => {
    // ...
    commit(//...)
      return data
    })
}

这样 Vue 组件调用方法时,终于可以获得data数据了。

总结#

其实这是一个很简单的错误,在我们写函数时,需要确认函数中的代码只是执行代码,还是需要输出值。如果需要输出值,不要忘记了使用return