Vue.js The mp3 files have been successfully added to an array, yet the audio remains silent

While coding, I faced an issue that I resolved by doing some research online and tweaking the sample code. As I added more lines of code, I encountered sections that were a bit confusing to me, but I managed to make them work. My main objective is to develop code that can play a sound to alert people waiting for service when it's their turn. The "filenames.value" variable already contains an array list of MP3 files, but currently, I'm having trouble getting any sound to play.

The error message ": onMounted is called when there is no active component instance to be associated with..." indicates that lifecycle injection APIs should only be used within the setup() function during execution. Ensure that any async setup() calls register lifecycle hooks before the first await statement.

<script setup>
import { ref, onMounted, computed } from 'vue';
import axios from 'axios';

const collection1Data = ref([]);
const collection2Data = ref([]);
const finalData = ref([]);
const latestfinalData = ref([]);

const fetchData = async () => {
  const [collection1Response, collection2Response] = await Promise.all([
    axios.get('https://koh-abx.com:50100/onboardshows'),
    axios.get('https://koh-abx.com:50100/onboardlands'),
  ]);
  collection1Data.value = collection1Response.data;
  collection2Data.value = collection2Response.data;
};

onMounted(async () => {
  await fetchData();
  setInterval(async () => {
    await fetchData();
    finalData.value = [];

    collection1Data.value.forEach(doc1 => {
      const matchingDoc = collection2Data.value.find(doc2 => doc1.idshow === doc2.idshow);
      if (matchingDoc) {
        finalData.value.push({
          idshow: doc1.idshow,
          numbershow: doc1.updatedAt > matchingDoc.updatedAt ? doc1.numbershow : matchingDoc.numbershow,
          ab: doc1.updatedAt > matchingDoc.updatedAt ? doc1.ab : matchingDoc.ab,
          updatedAt: doc1.updatedAt > matchingDoc.updatedAt ? doc1.updatedAt : matchingDoc.updatedAt
        });
      } else {
        finalData.value.push({
          idshow: doc1.idshow,
          numbershow: doc1.numbershow,
          ab: doc1.ab,
          updatedAt: doc1.updatedAt
        });
      }
    });

    collection2Data.value.forEach(doc2 => {
      if (!finalData.value.find(doc => doc.idshow === doc2.idshow)) {
        finalData.value.push({
          idshow: doc2.idshow,
          numbershow: doc2.numbershow,
          ab: doc2.ab,
          updatedAt: doc2.updatedAt
        });
      }
    });

    console.log(finalData.value);

    latestfinalData.value = finalData.value.filter(doc => (Date.now() - new Date(doc.updatedAt).getTime()) < 15000);
    console.log(latestfinalData.value);

    const filenames = computed(() => {
      return latestfinalData.value.map(item => {
        const digits = item.numbershow.toString().split('');
        return digits.map(digit => `https://koh-samui.com/sound/${digit}.mp3`);
      });
    });

    console.log(filenames.value);

    const audioRef = ref(null);
    const isPlaying = ref(false);

    onMounted(() => {
      const sounds = filenames.value;

      let currentSound = 0;
      audioRef.value = new Audio(sounds[currentSound]);
      audioRef.value.addEventListener("ended", () => {
        isPlaying.value = false;
        currentSound++;
        if (currentSound < sounds.length) {
          audioRef.value.src = sounds[currentSound];
          audioRef.value.play();
        }
      });

      if (!isPlaying.value) {
        isPlaying.value = true;
        audioRef.value.play();
      }
    });

  }, 2000);
});

</script>

Here is the modified code snippet where I attempted to resolve the issue related to playing the sound:

<script setup>
import { ref, onMounted, computed } from 'vue';
import axios from 'axios';

const collection1Data = ref([]);
const collection2Data = ref([]);
const finalData = ref([]);
const latestfinalData = ref([]);
const sounds = ref([]);
const audioRef = ref(null)
const isPlaying = ref(false)

const fetchData = async () => {
  const [collection1Response, collection2Response] = await Promise.all([
    axios.get('https://koh-abx.com:50100/onboardshows'),
    axios.get('https://koh-abx.com:50100/onboardlands'),
  ]);
  collection1Data.value = collection1Response.data;
  collection2Data.value = collection2Response.data;
};

onMounted(async () => {
  await fetchData();
  setInterval(() => {
    fetchData().then(() => {
      finalData.value = [];

      collection1Data.value.forEach(doc1 => {
        const matchingDoc = collection2Data.value.find(doc2 => doc1.idshow === doc2.idshow);
        if (matchingDoc) {
          finalData.value.push({
            idshow: doc1.idshow,
            numbershow: doc1.updatedAt > matchingDoc.updatedAt ? doc1.numbershow : matchingDoc.numbershow,
            ab: doc1.updatedAt > matchingDoc.updatedAt ? doc1.ab : matchingDoc.ab,
            updatedAt: doc1.updatedAt > matchingDoc.updatedAt ? doc1.updatedAt : matchingDoc.updatedAt
          });
        } else {
          finalData.value.push({
            idshow: doc1.idshow,
            numbershow: doc1.numbershow,
            ab: doc1.ab,
            updatedAt: doc1.updatedAt
          });
        }
      });

      collection2Data.value.forEach(doc2 => {
        if (!finalData.value.find(doc => doc.idshow === doc2.idshow)) {
          finalData.value.push({
            idshow: doc2.idshow,
            numbershow: doc2.numbershow,
            ab: doc2.ab,
            updatedAt: doc2.updatedAt
          });
        }
      });

      console.log(finalData.value);

      latestfinalData.value = finalData.value.filter(doc => (Date.now() - new Date(doc.updatedAt).getTime()) < 15000);
      console.log(latestfinalData.value);
    });

    const filenames = computed(() => {
      return latestfinalData.value.map(item => {
        const digits = item.numbershow.toString().split('');
        return digits.map(digit => `https://koh-abx.com/sound/${digit}.mp3`);
      });
    });

    console.log(filenames.value);
    sounds.value = filenames.value ;
    playSound();

  }, 5000);

});


const playSound = () => {
  let currentSound = 0;
  audioRef.value = new Audio(sounds.value[currentSound]);

  audioRef.value.addEventListener("ended", () => {
    isPlaying.value = false;
    currentSound++;
    if (currentSound < sounds.value.length) {
      audioRef.value.src = sounds.value[currentSound];
      audioRef.value.play();
    }
  });

  if (!isPlaying.value) {
    isPlaying.value = true;
    audioRef.value.play();
  }
};

</script>

Answer №1

Your code is facing an issue where the "onMounted" hook gets called twice, once outside the range function and then inside it. To resolve this issue, you should move the audioRef, isPlaying variables, and the onMounted hook referring to them out of the interval function. This ensures that the hook is registered only once, and both the interval function and the hook can access the variables.

Check out the modified code below:

<script>
import { ref, onMounted, computed } from 'vue';
import axios from 'axios';

const setup = () => {
  // Define reactive references to store data from API requests
  const collection1Data = ref([]);
  const collection2Data = ref([]);
  const finalData = ref([]);
  const latestfinalData = ref([]);

  // Function to fetch data from two API endpoints
  const fetchData = async () => {
    try {
      // Use Promise.all to make concurrent API requests
      const [collection1Response, collection2Response] = await Promise.all([
        axios.get('https://koh-abx.com:50100/onboardshows'),
        axios.get('https://koh-abx.com:50100/onboardlands'),
      ]);
      // Update the reactive references with API response data
      collection1Data.value = collection1Response.data;
      collection2Data.value = collection2Response.data;
    } catch (error) {
      // Log any errors to the console
      console.error(error);
    }
  };

  // Function to combine data from two API endpoints and filter unique values
  const combineData = () => {
    // Combine data from two API endpoints
    finalData.value = [...collection1Data.value, ...collection2Data.value];

    // Use Map to store unique data
    const uniqueData = new Map();
    finalData.value.forEach(doc => {
      const existingDoc = uniqueData.get(doc.idshow);
      if (existingDoc) {
        // If a document with the same idshow exists in the Map, update it with the latest data
        uniqueData.set(doc.idshow, {
          idshow: doc.idshow,
          numbershow: existingDoc.updatedAt > doc.updatedAt ? existingDoc.numbershow : doc.numbershow,
          ab: existingDoc.updatedAt > doc.updatedAt ? existingDoc.ab : doc.ab,
          updatedAt: existingDoc.updatedAt > doc.updatedAt ? existingDoc.updatedAt : doc.updatedAt
        });
      } else {
        // Add the document if a similar idshow is not present in the Map
        uniqueData.set(doc.idshow, {
          idshow: doc.idshow,
          numbershow: doc.numbershow,
          ab: doc.ab,
          updatedAt: doc.updatedAt
        });
      }
    });

    // Convert Map values to an array
    finalData.value = [...uniqueData.values()];
    // Sort the array by updatedAt in descending order and keep only the latest 10 items
    latestfinalData.value = finalData.value.sort((a, b) => a.updatedAt > b.updatedAt ? -1 : 1).slice(0, 10);
  };

  // Call the fetchData function when the component mounts
  onMounted(fetchData);

  // Use computed to monitor changes in collection1Data and collection2Data and invoke combineData
  computed(() => {
    combineData();
  });

  return {
    collection1Data,
    collection2Data,
    finalData,
    latestfinalData,
    fetchData
  };
};

export default {
  setup
};
</script>

I have optimized the code for improved performance

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

a single button with dual functionalities

I am new to the development field and have a question about jQuery. I want a single button to perform two different actions. For example, let's say we have a button labeled Pause/Resume. When I click on the button, it should first display "Pause", and ...

Tips for preventing a NodeJS script from crashing due to timeout being exceeded

Here is the issue I am encountering: I am attempting to scrape a website's content using NodeJS and puppeteer. Sometimes, my code halts with a Timeout Exceeded error. Is there a way for me to handle this timeout by implementing a function that will e ...

Is it true that JavaScript Date.parse doesn't recognize Alaska Timezones?

When using JavaScript's Date.parse, it handles Pacific Time without any issues: Date.parse('June 20 2015 10:22 PDT') However, it encounters issues with Alaska Time: Date.parse('June 20 2015 10:22 AKDT') Does anyone have a relia ...

using brackets to access objects in Vue.js

My function is designed as follows: field_validator(rule, value, callback) { this.form.setFieldsValue({ [rule.field]: null }) } I encountered an issue where I couldn't create the object like { rule.field: null }, and instead had to use brackets ...

Tips for patiently waiting for a function that is filled with promises

Consider the following function: const getData = () => { foo() .then(result => { return result; }) .catch(error => { return error; }); }; Even though getData does not directly return a promise, it internally handles asynchro ...

Encountered issue #98123: Failed to generate development JavaScript bundle during `gatsby develop` using Webpack

To set up a new Gatsby starter blog, I executed the following commands: gatsby new blog https://github.com/alxshelepenok/gatsby-starter-lumen cd blog gatsby develop However, while running gatsby develop, I encountered numerous errors labeled as ERROR # ...

To begin utilizing Node.js modules, you must use the `#` symbol as the starting point

Quoting the Nodejs documentation, available at this link require(X) from module at path Y 1. If X is a core module, a. return the core module b. STOP 2. If X begins with '/' a. set Y to be the filesystem root 3. If X begins with './ ...

We regret to inform you that there has been an integration error with Zoom SDK 2,3,5. You have reached the limit set by Zoom. Please verify

I'm currently working on integrating zoom web SDK version 2.3.5 into my Vue app that uses Laravel as the backend. However, I've encountered an error when trying to join a meeting. Here is the error message I received: You have been limited by Z ...

Customize Swiper js: How to adjust the Gap Size Between Slides using rem, em, or %?

Is there a way to adjust the spacing between slides in Swiper js using relative units such as 2rem? The entire page is designed with relative units. All measurements are set in rem, which adjusts based on the viewport size for optimal adaptability. For i ...

What is the best way to deactivate all active classes from buttons before selecting a new one?

I'm fairly new to working with Vue and I'm struggling to figure out how to properly handle buttons that need to have only one active at a time. Currently, I am using the activeBtn method but it doesn't seem to deactivate the previously activ ...

When using jQuery to add an item to a List, it disappears immediately after

I am facing an issue with the code I have. Whenever I click on the "Add" button to add an item, it briefly appears in the list but then disappears. I'm having trouble figuring out why this is happening. $(document).ready(function() { $("#submitB ...

The Ocelot API Gateway is a powerful tool for managing

I encountered an issue while working on my API gateway project. I initially installed the latest version of Ocelot (16.0.1), but it did not function correctly. The problem was resolved by reverting back to Ocelot version 15.0.6, while keeping my .NET Core ...

Trouble with clicking buttons in Java and Selenium web scraping

Hey everyone, Currently, I'm working on a Java Selenium script that automates clicking and filling forms for me. I've written a line of code that's causing me some trouble. The intention is to click on a button, but it's not happening ...

The issue of gallery image loading with the galleryView jQuery plugin is causing problems

Hi fellow developers, I could really use some assistance. I've been working on implementing the jquery galleryview plugin for my image gallery (check out my gallery here). Unfortunately, I'm running into an issue where the gallery is not loading ...

The functionality of Jquery appears to be malfunctioning on the Drupal platform, although it performs

I've built a jQuery carousel that is fully functional when tested locally, but encounters issues when uploaded to a Drupal platform. Surprisingly, the jQuery functions properly when entered through the Console. Here's the jQuery code: carousel = ...

Guide on accessing and displaying data table values in console.log using Vue.js and vuetify

Hello, I am new to Vue.js and I am trying to work with data tables. I have copied some code from the Vuetify website and I am attempting to call the desserts' names from a sample table using console.log. Below is the code snippet: <template> ...

I am experiencing difficulties with getting Google Analytics to function properly within my VuePress project

Recently, I started a new vuepress project I am attempting to implement Google Analytics to track its progress. However, there seems to be an issue connecting my project with Google Analytics I followed the Documentation Guide ( ) to include yarn add - ...

Guide to decoding JSONP data sent from a remote server

Working on retrieving data using JSONP. After observing the returned data in Firebug, I can confirm that it is being returned correctly. However, I am facing a challenge in figuring out how to parse it. Is the data returning as a nested array? The callback ...

React - Exploring the depths of functional components

Picture this: a straightforward form that showcases several unique components with customized layouts. The custom components include: <UsernameInput />, <PasswordInput />, <DateTimePicker />, <FancyButton />, <Checkbox /> Th ...

JQuery plugin for creating interactive date selection forms

Having some trouble creating a dynamic form. The datepicker seems to only work on the first row and I can't click it. Tried a few different codes but no luck so far. Below is the code excluding the PHP part, which is just for inserting into a database ...