Creating reactive behavior with a Promise initiated within a constructor - A guide

I am facing an issue with my Thing class. In the constructor, there is an asynchronous operation using fetch. Once the fetch completes, the result is assigned to a field in the Thing object:

  class Thing {
    constructor() {
      this.image = null
      this.load()
    }

    async load() {
      const response = await fetch('https://placekitten.com/200/300')
      const blob = await response.blob()
      this.image = await createImageBitmap(blob)
    }
  }

The problem arises when I try to use thing.image in a Vue component. Vue does not detect the change in image when the Promise resolves. This happens because in the constructor, this refers to the raw Thing and not Vue's reactive proxy wrapper. As a result, the assignment to this.image bypasses the proxy.

Moving the load call out of the constructor solves the reactivity issue as now this inside the load function refers to the reactive proxy. However, this makes it more complex to use the Thing class.

I am looking for a better way to handle this particular issue. Can you help?

Here is a minimal example: (Vue playground link):

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

  class Thing {
    constructor() {
      this.image = null
      this.load() // This does not trigger reactivity.
    }

    async load() {
      const response = await fetch('https://placekitten.com/200/300')
      const blob = await response.blob()
      this.image = await createImageBitmap(blob)
    }
  }

  const thing = reactive(new Thing())
  // thing.load() // This triggers reactivity as expected.
</script>

<template>
  <p v-if="thing.image">
    Image size is {{thing.image.width}}×{{thing.image.height}}
  </p>
  <p v-if="!thing.image">
    Loading...
  </p>
</template>

Answer №1

declare your class attribute as a reference

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

  class Object {
    constructor() {
      this.image = ref(null)
      this.initialize()
    }

    async initialize() {
      const response = await fetch('https://placekitten.com/200/300')
      const blob = await response.blob()
      this.image.value = await createImageBitmap(blob)
    }
  }

  const item = reactive(new Object())
  // item.initialize() // This triggers reactivity as intended.
</script>

<template>
  <p v-if="item.image">
    Image dimensions are {{item.image.width}}×{{item.image.height}}
  </p>
  <p v-if="!item.image">
    Loading...
  </p>
</template>

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

Unable to locate an element on the webpage due to a JavaScript-based error, which then becomes hidden after a few seconds. (Registration form)

While completing a registration form, I encounter a hidden message after clicking on the register button. Struggling to locate this elusive element has been an ongoing challenge for me. Unfortunately, my attempts to find the element have been unsuccessful ...

When I use AJAX to load a PHP file, the function's content returns as [object HTMLDivElement]

Hello there, When I use AJAX to load a PHP file, the content of my function returns [object HTMLDivElement], but if I load my function without loading the PHP file, it displays normally. index.php <h1>API Football</h1> <nav> ...

Issue with JQUERY where HTML select element is not visible

$(document).ready(function(){ var selArr = [ {val: 'corsair', text: 'Corsair'}, {val: 'evga', text: 'EVGA'}, {val: 'antec', text: 'Antec'} ]; $('#pSupply& ...

What is the best method for uploading a file through ajax in Django?

Just diving into this. Can someone guide me on how to use ajax to send a file to the server? I've managed to submit a String to my server, but I'm unsure about handling a File with ajax. upload_files.js $(document).on('submit', ' ...

Tips for choosing a href link from a JSON data structure

I'm struggling with JSON. I have a JSON object that looks like this: {main: "<a href="www.google.com"><img src="google_logo.png"></a>"} This is just a small part of my code. For example, I access the "main" object with json.main an ...

How can you ensure a script runs only once another script has completed its execution?

Consider the following code snippet I created to illustrate my idea: var extract = require("./postextract.js"); var rescore = require("./standardaddress.js"); RunFunc(); function RunFunc() { extract.Start(); console.log("Extraction complete"); ...

The Hidden Power of jQuery: Unleashing the Full Potential of .text()

I'm trying to make two values equal, but it's not working... var rowID = $("#@idSelectObjectGuid").val(); $($(".ls-grid-body tr").children("<a href="/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="240a64524770454648410a74564d ...

Tips for utilizing the beforeEach feature in node-tap?

Could someone please demonstrate how to utilize the beforeEach function? For more information, visit: . I am particularly interested in seeing an example using promises, although a callback version would also be appreciated. Below is a successfully functi ...

Resolving CORS issues: Troubleshooting communication between a React app and an Express server

After successfully running both the app and server locally, I encountered an issue upon deploying the express server. Whenever I try to make a request, I consistently receive the following error message: "has been blocked by CORS policy: Response to ...

Display alert only when focus is lost (on blur) and a dropdown selection was not made

Utilizing Google Maps Places for autocompletion of my input, I am aiming to nudge the user towards selecting an address from the provided dropdowns in order to work with the chosen place. A challenge arises when considering enabling users to input address ...

What advantages come from selectively importing a single function from a Node.js package on the backend, rather than importing the entire package?

Consider a scenario where I only require the ObjectId function from the mongoose package in my file. Are there any advantages (in terms of CPU usage, memory consumption, speed, etc.) to importing just that specific function instead of the entire mongoose ...

Encountering complications in compiling Vue components

As I'm fairly new to Vue.js, please bear with me. I've been working on a project where I created two new Vue components – one being a tab/toggle element and the other a cookie banner. However, when both are added to the page, the cookie banner ...

Having issues with the onSubmit event not being triggered for a react + material-ui form

I am currently using the mui box react component with the form set to the component property and an onSubmit attribute pointing to the submit handler I want to invoke. There is a submit button located at the bottom of the form. However, every time I click ...

The function is malfunctioning following the alert

I am experiencing an issue with my renumbering list function. I have a delete button on the list that triggers a confirmation alert, but after the alert is shown, the renumbering function stops working. Here is my script: <script type="text/javascript ...

A guide on arranging the JSON array within an AngularJS controller

Can someone assist me with sorting the JSON list provided below in the controller and then displaying it in the view? The orderBy filter only sorts one level, but I need it to sort recursively for all children. Input: R2 -->S4 ------>T5 ------> ...

Using Node.js to seamlessly read and upload files with Dropbox API

I am utilizing the Dropbox API to retrieve a file from the node.js file system and then transfer it into a designated Dropbox folder. The transfer process is successful, but the file ends up being empty, with a size of 0 bytes. var path = require("path") ...

What is the method to prolong the end date of fullCalendar.js through Javascript?

I am facing the same issue as this individual. I am unsure of how to add one day to the end date. I do not want to alter the database value, only modify it on the HTML page. Currently, this is my calendar (no Moment.js joke intended): $(document).ready(f ...

The Consequences of Using Undeclared Variables in JavaScript

What is the reason behind JavaScript throwing a reference error when attempting to use an undeclared variable, but allowing it to be set to a value? For example: a = 10; //creates global variable a and sets value to 10 even though it's undeclared al ...

Is it possible to upload an image file while the element is hidden with "display: none" property?

I need to upload a file using Selenium webdriver. Here is the URL of the page. <div class="async-upload__thumb item-image__area"> <div class="fab-dialog__thumb-drop-zone async-upload__thumb-drop-zone"> <p class="async-upload__thumb-ms ...

Angular HTTP client implementation with retry logic using alternative access token

Dealing with access tokens and refresh tokens for multiple APIs can be tricky. The challenge arises when an access token expires and needs to be updated without disrupting the functionality of the application. The current solution involves manually updati ...