Javascript function is returning an undefined value [duplicate]

I’m trying to display a browser’s IP address in a table, fetching the IP address from https://api.ipify.org. So, I did this:

function makeRequest(url, callback) {
          const xhr = new XMLHttpRequest();
          xhr.open('GET', url);
          xhr.onreadystatechange = function() {
            if (xhr.readyState === XMLHttpRequest.DONE) {
              if (xhr.status === 200) {
                callback(null, xhr.responseText); // Success: pass data to callback
              } else {
                callback(new Error('Request failed'), null); // Error: pass error to callback
              }
            }
          };
          xhr.send();
        }
        
let ipaddr = makeRequest('https://api.ipify.org?format=text', function(err, data) {
                if (err) {
                        return err;
                } else {
                        console.log('inside:" + data);
                        return data;
                }
        });
    console.log('IP: ' + ipaddr);

This is displayed on the console:

IP: undefined
IP inside:174.173.26.1

What am I doing wrong?

Vue 3: Scoped Slots & render() & h() function

This is a simplified situation. In reality, my code is more complex and larger. I am making a table component.

I am trying to pass data from a table to the column-component slot, which I pass through the data prop.
I think I can do this through the Celll.vue functional component.
But I am not sure that my reasoning is correct.

An example of what I want to get:

<table-component :data="dataTable">
    <column-component v-slot="slotProps">
      <span>Name:</span>
      <!-- GET DATA HERE -->
      <!-- <span>{{ slotProps }}</span> -->
    </column-component>

    <column-component v-slot="slotProps">
      <span>Age:</span>
      <!-- GET DATA HERE -->
      <!-- <span>{{ slotProps }}</span> -->
    </column-component>

    <column-component v-slot="slotProps">
      <!-- GET DATA HERE -->
      <span>City:</span>
      <!-- <span>{{ slotProps }}</span> -->
    </column-component>
  </table-component>

...

data() {
    return {
      dataTable: [
        { name: "Alex", age: "20", city: "Msk" },
        { name: "Bob", age: "22", city: "Paris" },
        { name: "Dilan", age: "21", city: "London" },
      ],
    };
  },

codesandbox: LIVE EXAMPLE

TableComponent.vue

<template>
  <table>
    <tr v-for="(row, rowIndex) in data" :key="rowIndex">
      <Celll
        v-for="(col, colIndex) in columns"
        :key="colIndex"
        :vnodes="col"
        :row="data"
      />
    </tr>
  </table>
</template>

<script>
import Celll from "./Celll.vue";

export default {
  components: {
    Celll,
  },
  props: {
    data: Array,
  },
  data() {
    return {
      columns: [],
    };
  },
  mounted() {
    this.columns = this.$slots.default();
  },
};
</script>

ColumnComponent.vue

<template>
  <slot />
</template>

<script>
export default {};
</script>

Celll.vue

<script>
import { h } from 'vue';

export default {
  props: {
    vnodes: {
      type: Object,
      required: true,
    },
    row: {
      type: [String, Number, Object, Array],
      required: true,
    },
  },

  render() {
    return h('td', null, this.vnodes);
  },
};
</script>

Echart sync graph with multiple y axies & grids with graph with only one y axies & one grid

I am trying to create binary graph.
For that reason I stack multiple line charts together under one chart.
enter image description here
Similarly to his example: https://echarts.apache.org/examples/en/editor.html?c=line-gradient

But when I try to sync this graph with other graphs that have only one X axis zoom function not work. (it work only on first chart).
The all other Yaxies inside the binary graph are synced properly.

Here is video example how it works:https://youtu.be/tBUjgRWfKc4

I need to be able to zoom on any X axies but i dont know haw to force grapsh to sync properly.

I try to catch echart zoom event and sub graphs emitting this event, but with different xAxisIndex that 0, that I expect but can it be the problem that other graphs don’t have xAxisIndex > 0?

If you have any idea how to sync this graph with others, I am glad to hear your opinion.

How to set different mock implementation for each test case?

I’m migrating from Jest to Vitest and struggling to provide a different mock value in each test case.

Basic example:

// test.ts

import { a } from './asd';

const { f } = vi.hoisted(() => {
    return {
        f: vi.fn(),
    };
});

vi.mock('../../../api/ApiProvider', () => ({
    f,
}));

describe('Test', () => {
    it('sample test case', () => {
        
        f.mockReturnValue(42);
        expect(a).toEqual(1);
    });

    it('sample test case2', () => {
        
        f.mockReturnValue(43);
        expect(a).toEqual(1);
    });
});
// asd.ts

import { f } from '../../../api/ApiProvider';
console.log('IMPORTING API PROVIDER', f());
export const a = 1;

The issue seems to stem from the fact that when the ApiProvider module is imported, it is cached and uses the initial mocking implementation of vi.mock which is an empty mock function, hence why IMPORTING API PROVIDER returns undefined. The f.mockReturnValue() calls seem to be ignored. I can provide a default implementation in the mock call, but what if I want to change this in another test case? Is there a way to disable the module import caching or am I doing something wrong?

The same code was working when using Jest and mockImplementation calls were applied in the test file.

The setup files do not import any modules so the caching is also not caused by this.

ref not being passed on second render of JSX

I have a react component for my video calling Application:

"use client";

import { useEffect, useRef, useState } from "react";
import { socket } from "@/lib/socket";
import * as mediasoupClient from "mediasoup-client";
import { useSearchParams } from "next/navigation";
import createProducerTransport from "./functions/createProducerTransport.js";
import createProducer from "./functions/createProducer.js";
import requestTransportToConsume from "./functions/requestTransportToConsume.js";

export default function Call({ name }) {
  const searchParams = useSearchParams();
  const roomName = searchParams.get("id");
  const localVideo = useRef();
  const localStream = useRef({});
  const runOnce = useRef(false);
  const joinRoomResp = useRef({});
  const device = useRef();
  const producerTransport = useRef(null);
  const videoProducer = useRef(null);
  const audioProducer = useRef(null);
  const [isAudioMuted, setIsAudioMuted] = useState(false);
  const [consumers, setConsumers] = useState({});
  const consumersRef = useRef({});

  const setValue = (arg) => {
    consumersRef.current = arg;
    setConsumers(arg);
    console.log("consumersRef", consumersRef.current);
  };
  useEffect(() => {
    consumersRef.current = consumers;
    console.log("consumersRef", consumersRef.current);
  }, [consumers]);

  useEffect(() => {
    if (runOnce.current) return;

    connect();

    socket.on("newProducersToConsume", (consumeData) => {
      // This Listener should only receive Consume data but not set up a connection
      console.log("newProducersToConsume");
      console.log(consumeData);
      requestTransportToConsume(
        consumeData,
        socket,
        device.current,
        setConsumers
      );
    });

    socket.on("userDisconnected", (pid) => {
      if (consumersRef.current[pid]?.consumerTransport) {
        consumersRef.current[pid].consumerTransport.close();
        console.log("consumerTransport closed");
      }
      const newState = { ...consumersRef.current };
      delete newState[pid];
      console.log("new state", newState);
      setValue(newState);
    });
    console.log("audioproducer", audioProducer.current);
    runOnce.current = true;
  }, []);

  const connect = async () => {
    const resp = await socket.emitWithAck("connected");
    if (resp) {
      console.log("socket connected");
      try {
        const joinRoomResp = await joinRoom();
        if (joinRoomResp === "roomFull") {
          alert("Room is full");
          throw new Error("Room is full");
        } else if (joinRoomResp === "error") {
          throw new Error("Error joining room");
        }
        if (device.current) {
          await gum();
          await sendFeed();
        }
      } catch (error) {
        console.error("Error joining room:", error.message);
      }
    } else {
      console.log("socket not connected");
    }
  };

  const gum = async () => {
    localStream.current = await navigator.mediaDevices.getUserMedia({
      audio: true,
      video: true,
    });
    localVideo.current.srcObject = localStream.current;

    // localVideo.current.muted = true;
  };
  const joinRoom = async () => {
    try {
      const res = await socket.emitWithAck("joinRoom", {
        userName: name,
        roomName,
      });
      if (res === "roomFull") {
        alert("Room is full");
        throw new Error("Room is full");
      }
      if (res === "error") {
        throw new Error("Error joining room");
      }
      device.current = new mediasoupClient.Device();
      await device.current.load({
        routerRtpCapabilities: res.routerRtpCapabilities,
      });
      console.log("joinRoomResp", res);
      // console.log("device", device.current);
      requestTransportToConsume(res, socket, device.current, setConsumers);

      return res;
    } catch (error) {
      console.error("Error joining room:", error.message);
    }
  };
  const sendFeed = async () => {
    producerTransport.current = await createProducerTransport(
      socket,
      device.current
    );
    console.log("Have the producer transport, now we need to produce");
    const producers = await createProducer(
      localStream.current,
      producerTransport.current
    );
    videoProducer.current = producers.videoProducer;
    audioProducer.current = producers.audioProducer;
    console.log("Producers are created!");
  };
  const muteAudio = () => {
    if (audioProducer.current.paused) {
      audioProducer.current.resume();
      socket.emit("audioChange", "unmute");
      setIsAudioMuted(false);
    } else {
      audioProducer.current.pause();
      socket.emit("audioChange", "mute");
      setIsAudioMuted(true);
    }
  };
  if (Object.keys(consumers).length === 0) {
    return (
      <div className="flex justify-center items-center h-screen">
        <h1 className="text-3xl text-white">
          Waiting for other participant...
        </h1>
        <video className="hidden" ref={localVideo} autoPlay playsInline />
      </div>
    );
  }
  return (
    <>
      {roomName && <h1>Room ID: {roomName}</h1>}
      <button onClick={muteAudio}>{isAudioMuted ? "Unmute" : "Mute"}</button>

      <video
        className="w-[100px] block h-auto rounded-sm absolute bottom-1 right-2 border border-white z-50"
        ref={localVideo}
        autoPlay
        playsInline
      />

      {Object.keys(consumers).length > 0 &&
        Object.keys(consumers).map((key) => {
          return (
            <div key={key} className="">
              <h3 className="absolute bottom-1 left-2 px-3 py-1 z-10 mx-2 my-1 rounded-sm bg-amber-300">
                {consumers[key].userName}
              </h3>

              <video
                autoPlay
                playsInline
                className="w-[100%] max-h-[100%]  transform -translate-y-1/2 top-1/2 absolute m-auto left-0 right-0 z-0"
                ref={(video) => {
                  if (video) {
                    video.srcObject = consumers[key].combinedStream;
                  }
                }}
              />
            </div>
          );
        })}
    </>
  );
}

The gum function is being called but when the JSX is rendered the video source is not updated and I am just left with an empty black box.

I would be grateful for any help.

I have tried a myriad of different things.
Particularly console logs and I’m really stuck now…

JS toLocaleString wrong timezone offset [closed]

In the following example I receive the wrong time:

const date_object = new Date("2025-11-04T18:30:00+02:00"); // german time. at 11. april the offset is UTC +2

console.log(date_object); // Raw Date object
console.log(new Date(date_object)); 

console.log(new Date(date_object).toLocaleString('de-DE', {
            timeZone: "Europe/Berlin",
            dateStyle: 'short',
            timeStyle: 'short'
        }) )

The output is

2025-11-04T16:30:00.000Z
2025-11-04T16:30:00.000Z
04.11.25, 17:30

But the last time should be 18:30. How can this be?

Problem with loading Google Maps with maps-api-v3 lib

Getting EpochMismatch error randomly while loading Google Maps in my React web App.
This error suddenly started coming since last 2 weeks, however my app is live since last 2 years.

Stack Trace

  at Ofb.Fg(/maps-api-v3/api/js/60/6/webgl.js:826:396)
  at dfb.next(/maps-api-v3/api/js/60/6/webgl.js:825:1348)
  at bY.d [as Tp](/maps-api-v3/api/js/60/6/webgl.js:160:99)
  at aY(/maps-api-v3/api/js/60/6/webgl.js:158:196)
  at Cob.Qg(/maps-api-v3/api/js/60/6/webgl.js:707:27)
  at Cob.Ug(/maps-api-v3/api/js/60/6/webgl.js:705:324)
  at r(/static/js/9105.71d2d0f6.js:2:70205)
Error: ~#!#~468~#!#~EpochMismatch,727,726~#!#~
  at SW(/maps-api-v3/api/js/60/6/webgl.js:126:3)
  at Ofb.Fg(/maps-api-v3/api/js/60/6/webgl.js:827:12)
  at dfb.next(/maps-api-v3/api/js/60/6/webgl.js:825:1348)
  at bY.d [as Tp](/maps-api-v3/api/js/60/6/webgl.js:160:99)
  at aY(/maps-api-v3/api/js/60/6/webgl.js:158:196)
  at Cob.Qg(/maps-api-v3/api/js/60/6/webgl.js:707:27)
  at Cob.Ug(/maps-api-v3/api/js/60/6/webgl.js:705:324)
  at r(/static/js/9105.71d2d0f6.js:2:70205)```

[Error: EpochMismatch] while loading Google Map

  [1]: https://i.sstatic.net/GsIYYkJQ.png
  [2]: https://i.sstatic.net/Myvw8ipB.png

Strapi 5 not able to create any new entry for Redirect

Getting issue for Strapi 5 while creating new redirect entries for package: “strapi-v5-redirects”: “^1.0.2”:

[2025-04-11 15:50:47.684] http: GET /admin/project-type (2 ms) 200
[2025-04-11 15:50:47.966] http: POST /admin/renew-token (5 ms) 200
[2025-04-11 15:50:47.966] http: GET /admin/init (18 ms) 200
[2025-04-11 15:50:48.085] http: GET /redirects?sort[0]=createdAt%3Adesc&pagination[pageSize]=10&pagination[page]=1 (0 ms) 401
[2025-04-11 15:50:54.764] http: POST /redirects (3 ms) 401
[2025-04-11 15:50:55.642] http: POST /redirects (3 ms) 401
[2025-04-11 15:50:56.759] http: POST /redirects (2 ms) 401

And not getting other options except findOne in directory “Strapi Admin > Settings > Roles > Public / Authenticated

Environment:

Strapi Version: 5.12.3
Node.js Version: 20.16.0
Database: Postgres
Plugin Version: strapi-v5-redirects ^1.0.2
Operating System: macOS

now it’s a plugin issue or any alternative way to solve this issue

How to configure PM2 with user-level Node.js installations managed by Ansible on OracleLinux?

I have an Ansible role that installs Node.js on OracleLinux machines. I’m installing Node.js (binary) at the user level (not globally) at the path: /home/{{ User }}/node/{{ node_version }}.

Problem

  • I need to use PM2 to manage my applications and want to configure it
    to use a specific Node.js version for each app. The challenge is
    that:

    Node.js is not installed globally Multiple Node.js versions might
    exist for the same user

If I install PM2 globally using a specific Node.js version like this:

/home/{{ User }}/node/node-22.14.0/bin/npm install -g pm2

Will PM2 be able to work with both older and newer Node.js versions that might be installed for the user? For example, if I later need to run applications with Node.js 20.x or 24.x, would the PM2 installed with Node.js 22.14.0 be compatible, or would I need separate PM2 installations for each Node.js version?

What’s the best way to install PM2 in this environment?

thanks

Smartphone attitude rotation from reference frame, airplane like

I am working on a mobile application using magnetometer, gyroscope and accelerometer to get information about device attitude as yaw, pitch and roll.

I am using Expo which has a DeviceMotion API giving me directly euler angles from IOS / Android attitude system APIs.

I try to manage to convert those angles relatives to “earth” after a user calibration or “zero”, to act like an EFIS screen in an airplane.

The smartphone will be installed in an arbitrary position in an airplane cockpit to give audio information about the airplane attitude (roll, pitch and yaw).
Once the device installed and fixed, the user will “calibrate” to have a reference zero for the fly.

I manage to rotate the angles by converting euler angles to quaternions and “multiply by inverse of attitude”, full example in js :

import { DeviceMotion, DeviceMotionMeasurement } from "expo-sensors";
import { quat } from "gl-matrix";
import { EventSubscription } from "react-native";

// Euler data in rad
export type EulerData = {
  roll: number;
  pitch: number;
  yaw: number;
};

export class Fusion {
  motion_sub?: EventSubscription;

  raw_euler_data?: EulerData;
  euler_data?: EulerData;

  reference_quaternion?: quat; // reference quaternion frame

  start() {
    // @ts-ignore
    this.motion_sub = DeviceMotion.addListener((data) => {
      this.raw_euler_data = motionRotationDataToEuler(data);
      this.tick();
    });

    DeviceMotion.setUpdateInterval(200); // 5Hz
  }

  stop() {
    this.motion_sub?.remove();
    this.motion_sub = undefined;
  }

  tick() {
    if (this.raw_euler_data) {
      if (this.reference_quaternion) {
        const currentQuat = eulerToQuat(this.raw_euler_data);
        const relativeQuat = quat.multiply(quat.create(), this.reference_quaternion, currentQuat);
        const euler = quatToEuler(relativeQuat);

        this.euler_data = euler;
      } else {
        this.euler_data = this.raw_euler_data;
      }

      let roll = radToDeg(this.euler_data.roll);
      let pitch = radToDeg(this.euler_data.pitch);
      let yaw = radToDeg(this.euler_data.pitch);

      console.log(roll, pitch, yaw);
    }
  }

  reference() {
    if (this.raw_euler_data) {
      const ref = JSON.parse(JSON.stringify(this.raw_euler_data)) as EulerData;
      const q = eulerToQuat(ref);

      this.reference_quaternion = quat.invert(quat.create(), q);

      this.tick();
    }
  }
}

// const degToRad = (deg: number) => deg * (Math.PI / 180);
const radToDeg = (rad: number) => rad * (180 / Math.PI);

// https://en.wikipedia.org/wiki/Conversion_between_quaternions_and_Euler_angles
const eulerToQuat = (data: EulerData) => {
  const { roll, pitch, yaw } = data;

  const cr = Math.cos(roll * 0.5);
  const sr = Math.sin(roll * 0.5);
  const cp = Math.cos(pitch * 0.5);
  const sp = Math.sin(pitch * 0.5);
  const cy = Math.cos(yaw * 0.5);
  const sy = Math.sin(yaw * 0.5);

  const q = quat.fromValues(
    sr * cp * cy - cr * sp * sy, // x
    cr * sp * cy + sr * cp * sy, // y
    cr * cp * sy - sr * sp * cy, // z
    cr * cp * cy + sr * sp * sy, // w
  );

  return q;
};

// https://en.wikipedia.org/wiki/Conversion_between_quaternions_and_Euler_angles
const quatToEuler = (q: quat): EulerData => {
  const [x, y, z, w] = q;

  // roll (x-axis rotation)
  const sinr_cosp = 2 * (w * x + y * z);
  const cosr_cosp = 1 - 2 * (x * x + y * y);
  const roll = Math.atan2(sinr_cosp, cosr_cosp);

  // pitch (y-axis rotation)
  const sinp = Math.sqrt(1 + 2 * (w * y - x * z));
  const cosp = Math.sqrt(1 - 2 * (w * y - x * z));
  const pitch = 2 * Math.atan2(sinp, cosp) - Math.PI / 2;

  // yaw (z-axis rotation)
  const siny_cosp = 2 * (w * z + x * y);
  const cosy_cosp = 1 - 2 * (y * y + z * z);
  const yaw = Math.atan2(siny_cosp, cosy_cosp);

  return {
    roll,
    pitch,
    yaw,
  };
};

const motionRotationDataToEuler = (motionData: DeviceMotionMeasurement): EulerData => {
  return {
    roll: motionData.rotation.gamma,
    pitch: motionData.rotation.beta,
    yaw: motionData.rotation.alpha,
  };
};

In this way, the angles are relatives to my reference frame.
It works if my device is perfectly aligned with the plane and horizontal.

I try to manage to make this angles relatives to the “world” and not to the device itself.
If my device is straight and vertical for example, the “roll” should be replaced by the “yaw” and inverse.

Could someone help me to understand those references, conversions and try to fix that ?

Solution to create Access Request Form for Tableau dashboard

Our team is currently looking for a solution to manage Tableau dashboard access requests efficiently. Ideally, we need:

  • A form where users can submit access requests (specifying market, category, etc.)
  • An approval workflow where requests are reviewed & approved by managers
  • Once approved, the user should automatically receive access to the Tableau dashboard

We are considering building this form as an Alteryx Analytical App but would love to hear your thoughts on:

  • Pros & cons of using Alteryx for this (e.g., performance, scalability, maintenance)
  • Alternative solutions/tools that might be more efficient (e.g., Power Automate, ServiceNow, or custom scripts)

Has anyone implemented something similar? Would love to hear your experiences & recommendations!

why isn’t my bookmark manager extension working?

I am currently learning javascript so I’m trying a lot of projects. I built a bookmark manager extension for chrome, but it keeps throwing an error when i try to add a bookmark.

I need it to append the saved bookmarks to the bookmark list but i keep getting an error saying

cannot read properties of null(reading appendChild)

here’s my html code:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <link rel="stylesheet" href="popup.css">
    <title>Bookmark Manager</title>
</head>
<body>
    <h1>Bookmark Manager</h1>
    <input type="text" id="urlInput" placeholder="Enter URL">
    <input type="text" id="titleInput" placeholder="Enter Title">
    <button id="saveButton">Save Bookmark</button>
    <h2>Your Bookmarks</h2>
    <ul id="bookmarkList"></ul>

    <script src="Popup.js"></script>
    
</body>
</html>type here

And my Popup.js:

document.getElementById('saveButton').addEventListener('click', saveBookmark);

function saveBookmark() {
    const url = document.getElementById('urlInput').value;
    const title = document.getElementById('titleInput').value;

    if (!url || !title) {
        alert('Please enter both a URL and a title.');
        return;
    }

    const bookmark = { parentId: "1" ,title, url };

    // Save bookmark to Chrome bookmarks
    chrome.bookmarks.create(bookmark, function(newBookmark) {
        console.log("Bookmark Created:", newBookmark);
        displayBookmark(newBookmark);
        clearInputs();
    });
}

function clearInputs() {
    document.getElementById('urlInput').value = '';
    document.getElementById('titleInput').value = '';
}

function displayBookmark(bookmark) {
    const bookmarkList = document.getElementById('bookmarkList');
    const li = document.createElement('li');
    li.textContent = bookmark.title;
    li.addEventListener('click', () => {
        chrome.tabs.create({ url: bookmark.url });
    });
    bookmarkList.appendChild(li);
}

// Load existing bookmarks on popup open
document.addEventListener('DOMContentLoaded', loadBookmarks);

function loadBookmarks() {
    chrome.bookmarks.getTree(function(bookmarkTreeNodes) {
        bookmarkTreeNodes.forEach(node => {
            if (node.children) {
                node.children.forEach(child => {
                    displayBookmark(child);
                });
            }
        });
    });
}