Vue: The async Apollo mixin function successfully logs a value, however it ultimately returns as undefined

I've encountered numerous async/return undefined queries on this platform, but despite trying various solutions, I'm unable to make any progress. My apologies if I overlooked something obvious.

In an attempt to improve reusability, I extracted all Apollo mutations from my main Vue code and placed them in a global mixin. However, it seems that I am struggling with the correct async/promise syntax for one of the queries.

Here is the mixin function I have created:

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");
              }
            });

      })
    }}

Additionally, here is the watcher being used:

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

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

I have tried several variations such as returning the 'ret' value directly without wrapping it in a promise, and using

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

in place of the then block within the watcher. Despite these attempts, the console consistently displays:

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

What am I overlooking? Why is the value not being passed to the watcher as expected?

Any advice provided would be greatly appreciated. Thank you.

Answer №1

I've come to realize that my issue involves dealing with nested promises. What I failed to recognize is that the Apollo query itself acts as a promise, and any return within that scope goes back to that promise rather than the calling function.

Therefore,

     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
          });
    }},

This results in not returning anything, leading to undefined.

To resolve this, all I needed to do was return the initial promise, which would then yield the desired result once resolved.

As a result, the calling function can simply utilize 'await' instead of the 'then' block.

The corrected final 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 updating 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);
    },

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

WebVTT captions on a Chromecast receiver as the default option

Trying to set up closed captions for chromecast using the default Chrome sender app but it's not working. The code is similar to the sample provided in the docs, seen here. I've shared a snippet that might be too sandboxed, view it on a normal ht ...

Injecting Javascript before page code in Chrome Extension Content Script allows for manipulation of webpage elements

I am currently working on developing a Chrome extension that involves injecting a script into a webpage before any other scripts present. This is crucial for my project as I am utilizing the xhook library to intercept XHR requests, which necessitates overw ...

Customize your Wordpress site with a JQuery load more button specifically designed for custom post types

I'm currently working on adding a "load more" button to my WordPress website in order to load my custom post types. I've managed to successfully make it load the posts, but I'm facing an issue where each time I load more posts, it replaces t ...

What is a global variable used for in JavaScript?

Here is the code snippet that I am currently working on: $(".link").each(function() { group += 1; text += 1; var links = []; links[group] = []; links[group][text] = $(this).val(); } ...

Executing synchronous animations in Jquery with callback logic

My jQuery plugins often rely on user-defined callbacks, like in the example below: (function($) { $.fn.myplugin = function(options) { var s = $.extend({}, options), $this = $(this); if (typeof s['initCallback'] = ...

Patiently anticipating the completion of a jQuery animation

I am currently working on some jQuery code that handles toggling containers and buttons. The specific snippet of code I am focused on is the following: var id = $(this).data('id'); if ($('#container').is(':visible')) { $( ...

A guide on dynamically altering text upon hovering over an element using Vue.js

On my website, I have the following HTML code: <div class="greetings"> <img @mouseover="hover='A'" @mouseleave="hover=''" src="a.png" alt="A" /> <img @mouseover="hover='B'" @mouseleave="hover=''" ...

Place an overlay element in the top-left corner of a perfectly centered image

Currently, there is an image that is centered on the screen using flexbox: .center-flex { display: flex; justify-content: center; } <div class="center-flex"> <img id="revealImage"> </div> An attempt is be ...

Is the concept of Controlled and Uncontrolled Components in VueJs similar to that of React?

When it comes to React, there is a distinction between controlled and uncontrolled components explained in detail at this link. Controlled components function within the React model where state is managed in the virtual DOM. In contrast, uncontrolled com ...

Dual Camera Toggle Functionality with Three.js Orbit Controls

I am facing an issue with two cameras in one scene, one viewport, and one renderer. I switch between cameras using HTML buttons. ISSUES Issue 1 When using camera1, there is no response from moving the mouse. However, when I switch to camera2, the orbit ...

Conditionally Binding Classes in Vue

My goal is to dynamically render a class based on the value of actionTypeCreate. The method actionTypeCreate simply returns a boolean value depending on the prop actionType that is passed to it. I have verified that this method is working correctly when tr ...

connecting parameters to functions in javascript

I'm attempting to execute a second query once the first query has been resolved by using the following code: const task1 = nextQuery => $.get('1.json', data => nextQuery()); const task2 = nextQuery => $.get('2.json', ...

tips for efficiently using keyboard to navigate through tabs in an unordered list

Utilizing unordered lists in this web application. I am looking to implement tab navigation with keyboard functionality. How can I achieve this? The first tab should contain text boxes, and when the user fills out a text box and presses the tab key, they s ...

Searching through different columns in various tables using the identical identifier, but with a reverse order

In the messages table for my chat application, I have columns labeled to and from, which store integers referencing users from the users table. My goal is to fetch all messages sent or received by the currently logged in user. Here is the query I am using ...

The isolate scope variable is becoming undefined within the link function

When working with a directive that takes a data object and a function in its isolate scope, I encountered an issue. Inside the link function, I declared a method to be triggered on a button click event. The problem is that while the value passed to the me ...

After the introduction of ReactiveFormsModule, the functionality of the Angular router has ceased

I am working on setting up a reactive form in Angular for a login page. Here is my login form: <form [formGroup]="loginForm" (ngSubmit)="login(loginForm.value)"> <div class="form-group"> <label for="username">Username</label> ...

What is preventing me from utilizing my JavaScript constructor function externally?

I have a question about how I create my object: var myViewModel = new MyViewModel("other"); Why am I unable to call myViewModel.setHasOne(value) from outside the viewmodel? Whenever I try, I encounter this error message: Uncaught TypeError: Cannot ca ...

Is it possible to refresh text in table without clearing icons?

Is there a way to maintain icons in table rows when editing text fields from a dialog? Currently, regardless of whether I use .html() or .text(), the icons disappear. I suspect that utilizing .content() may be a solution, but I'm unsure how to impleme ...

Can you please elaborate on CRUD operations in Node.js by providing examples to clarify?

Could you please provide a detailed explanation of CRUD operations in Node.js along with some examples? click here to view the image description ...

No matter what I do, I can't seem to stop refreshing the page. I've attempted to prevent default, stop propagation, and even tried using

Below is the code I have written for a login page: import { useState } from "react"; import IsEmail from "isemail"; import { useRouter } from "next/router"; import m from "../library/magic-client"; import { useEffect ...