Is it truly possible to return a reactive variable that updates its value asynchronously?

While reviewing the code of a frontend project developed in Vue3, I came across a unique construction that I have not encountered before. This has led to some confusion as I try to grasp how it operates. The concept involves assigning the result of an asynchronous call (such as fetching JSON data using fetch) to a reactive value.

The method I am accustomed to is demonstrated in the following code snippet (Vue Playground). Here, the use of setTimeout simulates the asynchronous operation, returning a Promise that is subsequently handled through a then() function to set the reactive variable msg.

<script setup>
import { ref } from 'vue'

const msg = ref('one')

const asyncCall = () => new Promise((resolve, reject) => {
  setTimeout(() => {
    resolve("two");
  }, 2000);
})

asyncCall().then(r => msg.value = r)

</script>

<template>
  <h1>{{ msg }}</h1>
</template>

On the other hand, the unconventional approach I encountered (Vue Playground) creates a local reactive variable within a function, executes the asynchronous call, and upon resolution, assigns the value to that local ref variable. The function then returns the ref value (visual sequence, actual execution differs).

<script setup>
import { ref } from 'vue'

const msg = ref('x')

const asyncCall = () => {
  const result = ref('one')
  setTimeout(() => {
    result.value = 'two'
  }, 2000)
  return result
}

msg.value = asyncCall()

</script>

<template>
  <h1>{{ msg }}</h1>
</template>

Although this alternative approach works, I find myself questioning:

  • ... the persistence of the local variable result beyond the scope of asyncCall, with its default value of
    one</code even before the callback in <code>setTimeout()
    occurs.
  • ... the ability to return result (a pointer) while assigning it to msg.value (a string), and witnessing successful functionality.
  • ... the presence of quotation marks around the displayed values ("one" and "two"), which has been addressed in a separate discussion here.

My question: Is this second approach valid? Is it recommended? Although it simplifies the code by consolidating the asynchronous process within the function, it deviates from traditional practices that I am familiar with.

Answer №1

What you are referring to as an async function is actually a function that returns a ref(), not truly asynchronous but rather executed immediately without any delay.

This function does have a side effect, such as the use of setTimeout. Eventually, it will update the returned ref in the future. When you assign this result to another ref, modifying the value of the returned one will also affect the one it was assigned to.

It is perfectly valid to assign ref() to a prop of a reactive() or another ref(), where updating the value of the returned ref will lead to updates in the assigned one as well.


To clarify my point further, in the example provided, initially, msg.value is set to x. It is then immediately assigned the value of ref('one'), and after two seconds, the inner ref()'s value changes to 'two'.
After this assignment, if you access msg.value, it will be a ref() and not a plain

string</code anymore. However, within the <code><template>
, nested refs are automatically unwrapped until reaching the actual .value.
However, caution should be taken when using msg.value inside the controller post-assignment, as it requires calling unref to retrieve the string value.

One potential issue with this approach is that watching msg may no longer detect changes following the assignment since its value remains the same: result. In order to address this concern, utilizing { deep: true } in the watcher's options would be necessary.

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

Updating dropdown selection with JavaScript

I have a dropdown select menu with two options. I am using JavaScript to retrieve the selected value from the drop-down menu and display it in a text area. Here is my code: $(document).ready(function () { $('#pdSev').change(function () { ...

Leverage dynamically loaded HTML classes using jQuery

My page has dynamically loaded divs with the class name product. The issue I am facing is that Jquery does not seem to recognize this class when using the code below. Clicking on the product divs doesn't trigger any action, while clicking on nav-eleme ...

Determine if an array of objects within React JS contains additional objects

I need assistance in displaying the <div className="songs-list-header-col">Album</div> only if the tracks array contains the artist property as an object. In cases where the artist is not an object, I do not want to display the <di ...

Formatting Date and Time in the Gridview of my Asp.net Application

I have been using this format to display the date and time in a grid. The issue I am facing is that I cannot retrieve the exact HH:MM from the database. Even though the database shows 11:11, my grid is displaying 11:03 instead. Here is the value stored in ...

Set the camera to view the world from a y-coordinate of 0 and descend

How can I make the top of the render area in Three.js point to y=0 in the world? I also want the camera to look straight (lookAt) These are my current values: camera = PerspectiveCamera camera.position.z = 1895.8448868133867 camera.fov = 20 screen.width ...

Collecting information from form submissions, accessing data from the database, and displaying the results

I am currently working on a project using nodejs, express, and mongodb within the cloud9 IDE. My goal is to create a page with a form that allows users to input data, search for corresponding information in the database, and display that data on the same ...

Receiving a Javascript Callback from Paypal

Is it possible to receive a JavaScript callback after a successful PayPal purchase made using a button? I am aware of IPN, but it requires a return URL. My main goal is to simply determine if a user has completed a purchase with the button. ...

What causes certain event handlers to be activated when using dispatchEvent, while others remain inactive?

When it comes to event-based JS, there are two main APIs to consider: event listeners and event handlers. Event listeners can be registered using addEventListener, while event handlers are typically registered with an API similar to target.onfoobar = (ev) ...

Generate a request to load JSON data

On my webpage, I have several external JSON files that need to be loaded. I'm looking for a way to specify the order in which they should be loaded. Using JavaScript for this task, here is an example: const func1 = () => { $.getJSON(json1, re ...

Why Changing the Width of a Flexbox Container Doesn't Impact Its Children?

Attempting to use TweenLite to animate the width of the blue sidebar down to zero, however facing an issue where the content breaks outside the parent's bounds. https://i.stack.imgur.com/4rEVr.png It is unusual for this to happen with Flexbox, given ...

Creating a cascading select menu based on the selected value of another select menu

I am in the process of creating a menu that displays two lists for regions: one <select> for selecting the region and another <select> for choosing from available municipalities within that region. I have set up a <form> and I utilize Jav ...

Inject environment variable into SCSS file while using webpack

I'm new to webpack and I need help with reading a specific value, which is the env variable from the webpack.config.js file, in a sass file. This will allow me to have different CSS styles based on the environment. For example: If the env is set to ...

React Data Filtering Techniques

I'm currently facing an issue with the if statement in my Action component. I'm struggling to figure out how to handle the case when an item is not found in the data from a JSON file. I have a Filtering function in a Context that I am using globa ...

alerting the user of any modifications made to a table within the database

In my current Spring project, I am seeking the optimal solution to improve system performance. Should I implement a solution using Javascript or create a custom method in Java? ...

Best approach for retrieving and adding a large number of images when dealing with slower connections

Currently, I am retrieving 100-200 images using a combination of ajax-php-mongodb. The process involves ajax making an initial call with parameters, php on the server side locating the appropriate mongo document containing all image file ids in grid fs, fe ...

Vue SPA authentication

After following various guides on implementing authentication in my Vue application with a .NET Core API backend, I have some questions. You can check out this guide: https://medium.com/dev-bits/a-guide-for-adding-jwt-token-based-authentication-to-your-si ...

Learn how to use JavaScript to parse binary files

Is there a way to interpret this binary data below? Binary2 { sub_type: 0, buffer: Buffer(16) [ 12, 15, 64, 88, 174, 93, 16, 250, 162, 5, 122, 223, 16, 98, 207, 68 ], position: 16 } I've attempted different methods like using ...

The screen suddenly turns black just moments after starting the video

Currently, I am utilizing the Youtube JavaScript API to embed videos on my webpage and control a playlist. However, I keep encountering an error where the video turns black right after loading the title, play icon, and loading icon. Initially, it seems lik ...

A Sweet Alert to Deliver your Morning Toasty Message

I seem to be encountering an issue with my toast message. Instead of the toast popping up immediately after submitting the form, it keeps appearing even if I haven't submitted the form and even when navigating from another page to this one, the toast ...

Spying on functions within Vue 3 setup() is not allowed

What is the best way to create a Jest test that triggers the function resetTimer and verifies that startTimer is also triggered? JS Code: setup () { const startTimer = () => { // ... }; const resetTimer = () => { startTi ...