javascriptvue.jsasync-awaitvue-apollovue-mixin

Vue: Async Apollo mixin function prints a value, but returns undefined


Async/return undefined queries are common on here but I've tried all permutations of answers and seem to be getting nowhere... Apologies if I couldn't find it.

I have taken all Apollo mutations out of my main Vue code into a global mixin so I can reuse, however I'm clearly not getting the async/promise syntax correct for one of the queries.

This is the mixin function:

async DBgetGroupName(id) {
      if (id == null) {
        return process.env.VUE_APP_DEFAULT_GROUP_NAME;
      } else {
        await this.$apollo
          .query({
            query: GET_GROUP,
            variables: {
              id: id,
            },
          })
          .then((data) => {
            let ret = data.data.groups[0].group_name;
            return new Promise((resolve, reject) => {
              if (ret !== undefined) {
                console.log("Return value is " + ret);
                resolve(ret);
              } else {
                reject("Error");
              }
            });

      })
    }}

And this is the calling watcher.

watch: {
     selected: async function() {
      let vars = {
        id: null,
        name: "",
      };

      vars.id = this.selected;
       this.DBgetGroupName(vars.id).then((data) => {
        console.log("Name is " + data);
      });
    },
  }

Other permutations I've tried are simply returning the 'ret' value without wrapping in a promise, and using

let data = await this.DBgetGroupName(vars.id)

in the watcher instead of the then block. The result in the console is always

Return value is Test Group [or whichever group I've selected, ie the correct value]
Name is undefined

What am I missing? Why isn't the value coming through to the watcher?

Thank you for any advice.


Solution

  • It turns out that I'm dealing with nested promises. What I didn't realize is that the Apollo query itself is a promise, and anything returned within that block is actually returning to that promise, rather than to any calling function.

    So

         async DBgetGroupName(id) {
          if (id == null) {
            return process.env.VUE_APP_DEFAULT_GROUP_NAME;
          } else {
            await this.$apollo. // this call returns a promise
              .query({
                query: GET_GROUP,
                variables: {
                  id: id,
                },
              })
              .then((data) => {
                let ret = data.data.groups[0].group_name;
                console.log("Return value is "+ret)
                return ret // this returns to the above promise, not the overall function
              });
        }},
    

    Doesn't return anything, hence undefined.

    So therefore to get it to work I just needed to return the initial promise, which would then return the ultimate return value when it is resolved.

    Consequently, the calling function can just use await, rather than the then block.

    Final, correct code:

         async DBgetGroupName(id) {
          if (id == null) {
            return process.env.VUE_APP_DEFAULT_GROUP_NAME;
          } else {
            return await this.$apollo  //return this promise
              .query({
                query: GET_GROUP,
                variables: {
                  id: id,
                },
              })
              .then((data) => {
                let ret = data.data.groups[0].group_name;
                console.log("Return value is "+ret)
                return ret. //value provided to above promise for returning
              });
        }},
    
    

    and calling watcher:

         selected: async function() {
          let vars = {
            id: null,
            name: "",
          };
          vars.id = this.selected;
          let data = await this.DBgetGroupName(vars.id)
          console.log("Name is " + data);
        },