How wait a "Array for each" function? - reactjs

I got a little problem with synchronous/asynchronous system in the function "Array.foreach".
I don't know how to force my code to wait its end.
I tried to use await/async system but my code did not wait the code in "async responseDB =>".
This is my class:
...
let responsesDTO = [];
await Array.prototype.forEach.call(await searchResponsesByQuestionAndUserId(questions[cpt].idquestion, idUser), async responseDB => {
if(responseDB !== undefined){
const responseDTO = {
response_id:0,
response_text:"",
response_type:""
}
const responseEntity = await searchResponseByResponseId(responseDB.response_id);
responseDTO.response_id = responseDB.response_id;
responseDTO.response_text= responseEntity.text;
responseDTO.response_type= responseDB.type;
responsesDTO.push(responseDTO);
}
});
questionResponse.responses=responsesDTO;
questionResponses[cpt]=questionResponse;
}
Could you help me please? Thanks in advance.

I had to mock your async functions. However, the relevant part is to use for..of instead of forEach
async function searchResponsesByQuestionAndUserId() {
let responsesDB = [];
for (let i = 0; i < 10; i++) {
responsesDB.push({
response_id: parseInt(1000 * Math.random(), 10),
type: 'whatever ' + i
});
}
return new Promise((res) => {
window.setTimeout(() => {
res(responsesDB);
}, 1500);
});
}
async function searchResponseByResponseId(response_id) {
return new Promise((res) => {
window.setTimeout(() => {
res({
text: 'text for response ' + response_id
});
}, 300);
});
}
async function getResponsesDTO() {
let responsesDTO = [],
responsesDB = await searchResponsesByQuestionAndUserId();
for (let responseDB of responsesDB) {
if (responseDB === undefined) {
continue;
}
let responseDTO = {
response_id: 0,
response_text: "",
response_type: ""
},
responseEntity = await searchResponseByResponseId(responseDB.response_id);
responseDTO.response_id = responseDB.response_id;
responseDTO.response_text = responseEntity.text;
responseDTO.response_type = responseDB.type;
responsesDTO.push(responseDTO);
console.log({responseDTO});
}
return responsesDTO;
}
getResponsesDTO().then(responsesDTO => {
console.log(responsesDTO);
});

Related

Memory leak warnings in electron

I'm getting memory leak warning in the console for my Electron app, i don't know what to do to increase limit. It's causing it everytime i run the app.
Does the error is linked to uiohook? Or did i miss something here?
How can i use emitter.setMaxListeners() in my case? I have no clue of how to fix it, and hwo to increase the memory leak.
[3452:1014/104426.056:ERROR:service_worker_storage.cc(1904)] Failed to delete the database: Database IO error
(node:21792) MaxListenersExceededWarning: Possible EventEmitter memory leak detected. 11 terminate-timer listeners added to [EventEmitter]. Use emitter.setMaxListeners() to increase limit
(Use `electron --trace-warnings ...` to show where the warning was created)
(node:21792) MaxListenersExceededWarning: Possible EventEmitter memory leak detected. 11 set-activity listeners added to [EventEmitter]. Use emitter.setMaxListeners() to increase limit
Electron
const electron = require('electron');
const BrowserWindow = electron.BrowserWindow;
const dialog = electron.dialog;
const desktopCapturer = electron.desktopCapturer;
const idle = electron.powerMonitor;
const remote = electron.remote;
const notification = electron.Notification;
const globalShortcut = electron.globalShortcut;
const screen = electron.screen;
const ipcMain = electron.ipcMain;
const app = electron.app;
const isDev = require('electron-is-dev');
const path = require('path');
const activeWindows = require('electron-active-window');
const activeWindowPage = require('active-win');
const BMParser = require('bookmark-parser');
const axios = require('axios');
const uiohook = require('uiohook-napi');
const { autoUpdater } = require("electron-updater");
const debug = require('debug')('Franz:ipcApi:autoUpdate');
const dns = require("dns");
const activity = { is_mouse: 0, is_keyboard: 0 };
const headers = {
'Content-Type': 'application/json;charset=UTF-8',
"Access-Control-Allow-Headers": "*",
"Access-Control-Allow-Origin": "*",
"Accept": "application/json"
}
const sessionUser = null;
let updateInterval = null;
app.disableHardwareAcceleration();
electron.powerSaveBlocker.start('prevent-app-suspension');
//electron.commandLine.appendSwitch ("disable-http-cache");
// Change App Name on Windows
if (process.platform === 'win32')
{
app.setAppUserModelId('Rubii');
}
let apiEndpoint = "http://creaz:81/xorix/api"; // Brian
let frameUrl = 'http://localhost:3000'; // Brian
//if (isDev) { // or if(process.env.NODE_ENV)
// apiEndpoint = "http://creaz:81/xorix/api";
// frameUrl = 'http://localhost:3000';
//}
var internetAvailable = require("internet-available");
let isConnected = false;
let counterInternet = 0;
let allowSendInternetNotification = 1;
async function liveInternetCheck() {
var userSessionCheck = await getSessionUser();
// Most easy way
internetAvailable({
domainName: "rubii.com",
// Provide maximum execution time for the verification
timeout: 10000,
// If it tries 10 times and it fails, then it will throw no internet
retries: 10
}).then(() => {
// Available Internet
isConnected = true;
counterInternet++;
if(counterInternet > 3 && allowSendInternetNotification == 0) {
allowSendInternetNotification = 1;
}
}).catch(() => {
// Not available internet
isConnected = false;
if(isConnected == false && userSessionCheck && allowSendInternetNotification == 1) {
var message = 'Your internet has been disconnected! Please login again';
new notification({ title: 'Ooops', body: message }).show();
// Logout the user in the other end
win.webContents.send("terminate-timer", "hello");
allowSendInternetNotification = 0;
counterInternet = 0;
}
});
}
autoUpdater.on("update-available", (_event, releaseNotes, releaseName) => {
const dialogOpts = {
type: 'info',
buttons: ['Ok'],
title: 'Update Available',
message: process.platform === 'win32' ? releaseNotes : releaseName,
detail: 'A new version download started. The app will be restarted to install the update.'
};
dialog.showMessageBox(dialogOpts);
updateInterval = null;
});
autoUpdater.on("update-downloaded", (_event, releaseNotes, releaseName) => {
const dialogOpts = {
type: 'info',
buttons: ['Restart'],
title: 'Application Update',
message: process.platform === 'win32' ? releaseNotes : releaseName,
detail: 'A new version has been downloaded. Restart the application to apply the updates.'
};
dialog.showMessageBox(dialogOpts).then((returnValue) => {
if (returnValue.response === 0) autoUpdater.quitAndInstall()
});
});
function checkUpdate() {
updateInterval = setInterval(() => autoUpdater.checkForUpdates(), 600000);
}
let win;
ipcMain.on('close-me', (evt, arg) => {
new notification({ title: 'Ooops', body: 'We hope to see you again!' }).show();
app.quit()
});
function determineScreenShotSize() {
var screenSize = screen.getPrimaryDisplay().workAreaSize
return {
width: screenSize.width,
height: screenSize.height
}
}
async function takeScreenshot() {
var user = await getSessionUser();
var timer = await getSessionTimer();
if (user && timer) {
if (timer.timer == 1) {
//console.log('Gathering screens...');
//console.log(app.getPath('pictures'));
const thumbSize = determineScreenShotSize();
const workaroundTimestamp = Date.now();
const options = {
types: ['screen'],
thumbnailSize: { ...thumbSize, workaroundTimestamp }
};
desktopCapturer.getSources(options).then((sources) => {
console.log('Sources received:' + sources.length);
sources.forEach(function (source) {
const sourceName = source.name.toLowerCase();
//console.log(sourceName);
if (['entire screen', 'screen 1'].includes(sourceName)) {
var the_screenshot = source.thumbnail.toPNG();
var data = {
user_id: user.id,
company_id: timer.company_id,
image: the_screenshot.toString('base64')
}
axios.post(apiEndpoint + "/desktop/save_screenshots", data, {
headers: headers
})
.then((response) => {
// console.log(response);
})
.catch((error) => {
//console.log(error);
})
}
})
}).catch(console.error);
}
}
}
function saveSoftware() {
(async () => {
var options = [];
var software = await activeWindowPage();
var user = await getSessionUser();
var timer = await getSessionTimer();
if (user && timer) {
if (timer.timer == 1) {
software.user = user;
software.timer = timer;
axios.post(apiEndpoint + "/desktop/save_app", software, {
headers: headers
})
.then((response) => {
//console.log(response);
})
.catch((error) => {
//console.log(error);
})
}
}
})();
}
function getSessionUser() {
return win.webContents.executeJavaScript('sessionStorage.getItem("user");', true)
.then(result => {
if (result) {
return JSON.parse(result);
}
});
}
function getSessionTimer() {
return win.webContents.executeJavaScript('sessionStorage.getItem("timer");', true)
.then(result => {
if (result) {
return JSON.parse(result);
}
});
}
async function generateActivity() {
win.webContents.send("set-activity", activity);
// We reset after we send it
activity.is_mouse = activity.is_keyboard = 0;
}
function secondsToHms(d) {
d = Number(d);
var h = Math.floor(d / 3600);
var m = Math.floor(d % 3600 / 60);
var s = Math.floor(d % 3600 % 60);
var hDisplay = h > 0 ? h + (h == 1 ? " hour, " : " hours, ") : "";
var mDisplay = m > 0 ? m + (m == 1 ? " minute, " : " minutes, ") : "";
var sDisplay = s > 0 ? s + (s == 1 ? " second" : " seconds") : "";
return hDisplay + mDisplay + sDisplay;
}
function createWindow() {
win = new BrowserWindow({
width: 1200,
height: 900,
frame: true,
webPreferences: {
webSecurity: false,
nodeIntegration: true,
enableRemoteModule: true,
contextIsolation: false,
backgroundThrottling: false
}
});
//win.loadURL('https://desktop.rubii.com');
win.loadURL(frameUrl, { "extraHeaders": "pragma: no-cache\n" });
// http://localhost:3000
//win.webContents.openDevTools();
//win.removeMenu(); // Brian
// or set the Menu to null
//win.setMenu(null); // Brian
// Reload cache
win.webContents.reloadIgnoringCache();
// Keyboard activity
uiohook.uIOhook.on('keydown', (e) => {
//console.log('Keyboard!')
activity.is_keyboard = 1;
})
// Mouse activity
uiohook.uIOhook.on('mousemove', (e) => {
//console.log('mouse');
activity.is_mouse = 1;
})
// Start listener for keyboard and mouse
uiohook.uIOhook.start();
win.on('close', function () {
win = null;
})
}
app.whenReady().then(createWindow).then(checkUpdate);
app.on('window-all-closed', function () {
app.quit();
});
app.on('activate', function () {
if (win == null) {
createWindow();
}
})
setInterval(takeScreenshot, 10 * 60 * 1000); // 10 minutes
setInterval(saveSoftware, 5 * 1000); // 5 seconds
setInterval(generateActivity, 1 * 1000);
setInterval(function() { liveInternetCheck(); }, 10 * 1000); // 10 seconds
Render
ipcRenderer.on("terminate-timer", function (event, data) {
// Logout if there is no internet connection
handleLogout();
});
// Set activity if there were any keyboard, mouse
ipcRenderer.on("set-activity", function (event, data) {
// If the timer is on
if(timer) {
setActivity(data);
}
});

Why my const var is empty but the related filter works

RemoveArea(area: models.Area) {
let messages: string[] = [];
messages = messages.concat(this.getMessagesFromDeletingArea(area));
this._translate.get('QuestionGroup_RemoveAreaConfirm',
{ thisCaption: area.caption[this.BlueContext.currentLanguage] }).subscribe(nextCaption => {
this.dialogsService.confirm(nextCaption, messages)
.subscribe(confirmed => {
if (confirmed) {
this._areaService.removeArea(this.dashboardConfiguration, area, this.BlueContext.currentLanguage);
const index = this.areas.findIndex(a => a.id === area.id);
if (index > -1) {
this.areas.splice(index, 1);
//here
this.dashboardConfiguration.widgets.forEach(wAId => {
const allWidgetByAreaId = wAId.widgets.filter(w => w.areaId === area.id);
allWidgetByAreaId.forEach(w => {
w.areaId = null;
});
});
}
}
});
});
}
The filter is working but the const var (allWidgetByAreaId) is undefined and empty so "for each " does not work. Would you please help?

Why doesn't the effect get current from the link?

I need to get localMediaStream in one effect, while it is set in another effect. Please tell me why in this context it is always null (if you do not set it in the same effect), but in this case I have a duplicate userMedia. Consequences - the camera does not go out when I call track.stop(). Based on this package
const peerConnections = useRef({});
const localMediaStream = useRef(null);
const peerMediaElements = useRef({
[LOCAL_VIDEO]: null,
});
useEffect(() => {
async function handleNewPeer({peerID, createOffer}) {
if (peerID in peerConnections.current) {
return console.warn(`Already connected to peer ${peerID}`);
}
peerConnections.current[peerID] = new RTCPeerConnection({
iceServers: freeice(),
});
peerConnections.current[peerID].onicecandidate = event => {
if (event.candidate) {
socket.emit(ACTIONS.RELAY_ICE, {
peerID,
iceCandidate: event.candidate,
});
}
}
let tracksNumber = 0;
peerConnections.current[peerID].ontrack = ({streams: [remoteStream]}) => {
tracksNumber++
if (tracksNumber === 2) { // video & audio tracks received
tracksNumber = 0;
addNewClient(peerID, () => {
if (peerMediaElements.current[peerID]) {
peerMediaElements.current[peerID].srcObject = remoteStream;
} else {
// FIX LONG RENDER IN CASE OF MANY CLIENTS
let settled = false;
const interval = setInterval(() => {
if (peerMediaElements.current[peerID]) {
peerMediaElements.current[peerID].srcObject = remoteStream;
settled = true;
}
if (settled) {
clearInterval(interval);
}
}, 1000);
}
});
}
}
/*localMediaStream.current = await navigator.mediaDevices.getUserMedia({
audio: audio,
video: video
})*/
localMediaStream.current.getTracks().forEach(track => { // localMediaStream null
peerConnections.current[peerID].addTrack(track, localMediaStream.current);
});
if (createOffer) {
const offer = await peerConnections.current[peerID].createOffer();
await peerConnections.current[peerID].setLocalDescription(offer);
socket.emit(ACTIONS.RELAY_SDP, {
peerID,
sessionDescription: offer,
});
}
}
socket.on(ACTIONS.ADD_PEER, handleNewPeer);
return () => {
socket.off(ACTIONS.ADD_PEER);
}
}, []);
// The installation, everything is as in the source, it did not work until I added the crutch above, but when it came to stopping the video stream, a bug appeared with the camera always on
useEffect(() => {
async function startCapture() {
console.log('start capture');
localMediaStream.current = await navigator.mediaDevices.getUserMedia({
audio: audio,
video: video
}).catch(console.log);
addNewClient(LOCAL_VIDEO, () => {
const localVideoElement = peerMediaElements.current[LOCAL_VIDEO];
if (localVideoElement) {
localVideoElement.volume = 0;
localVideoElement.srcObject = localMediaStream.current;
}
});
}
startCapture().then((data) => socket.emit(ACTIONS.JOIN, {room: roomID})).catch((e) => console.error(e)).finally(() => console.log('finally'));
console.log(roomID);
return () => {
localMediaStream.current.getTracks().forEach(track => track.stop());
socket.emit(ACTIONS.LEAVE);
};
}, [roomID]);
Thanks you very much.

Reactjs Websocket connection is not stable

I'm new to Reactjs. I have a code written in Reactjs. The code below is to get a response from server by using Websocket. Every 10 secs, under the componentDidUpdate it will run the retrieveServerData to get the latest information.
I have 3 enquiries that I need to send to server, for each enquiry i will open a new socket inside ws.onmessage() . This works well, data can be retrieved correctly with no any connection error.
class Subject extends React.Component {
componentDidUpdate = (prevProps, prevState) => {
setTimeout(() => {
this.setState({
//set some state
}, () => {
this.interval = setInterval(() => this.retrieveServerData(), 5000);
});
}, 10000);
}
retrieveServerData = () => {
let statusEn = "enabled";
let enquiry = ["data1", "data2", "data3"];
for (let i = 0; i < 2; i++) {
let dataMethod = {
Name: "AAA",
Subject: "Math",
Day: "Thursday",
Parameters: { Data: enquiry[0] }
};
let ws = new WebSocket("ws://localhost:XXX");
let dataMethodInString = JSON.stringify(dataMethod);
ws.onopen = () => {
ws.send(dataMethodInString);
};
ws.onmessage = (event) => {
if (event.data !== "Socket server connected") {
if (!event.data.includes("Error")) {
let myArray = ProcessElement(event.data);
console.log("myArray 0: ", commands[0], myArray);
//2nd
let ws = new WebSocket("ws://localhost:XXX");
let dataMethodCopy = JSON.parse(JSON.stringify(dataMethod));
dataMethodCopy["Parameters"] = { Data: commands[1] };
let dataMethodInString = JSON.stringify(dataMethodCopy);
ws.onopen = () => {
ws.send(dataMethodInString);
};
ws.onmessage = (event) => {
if (event.data !== "Socket server connected") {
if (event.data.includes("Error") === false) {
let myArray = ProcessElement(event.data);
console.log("myArray 1: ", myArray);
let ws = new WebSocket("ws://localhost:XXX");
let dataMethodCopy = JSON.parse(JSON.stringify(dataMethod));
dataMethodCopy["Parameters"] = { Data: commands[2] };
let dataMethodInString = JSON.stringify(dataMethodCopy);
ws.onopen = function () {
ws.send(dataMethodInString);
};
ws.onmessage = (event) => {
if (event.data !== "Socket server connected") {
if (event.data.includes("Error") === false) {
let myArray = ProcessElement(event.data);
console.log("myArray 2: ", myArray);
} else {
console.log("myArray 2 error ");
}
ws.close(1000, "request 2 fetch completed");
}
};
} else {
console.log("myArray 1 error ");
}
ws.close(1000, "request 1 fetch completed");
}
};
} else {
console.log("myArray 0 error ");
}
ws.close(1000, "request 0 fetch completed");
}
};
}
};
}
I tried to simplify the code above, instead of opening 1 connection for each enquiry, I want to have 1 connection and send 3 enquiries.
retrieveServerData = () => {
let statusEn = "enabled";
let commands = ["data1", "data2", "data3"];
for (let i = 0; i < 2; i++) {
let commandResponse = [];
const getDataMethod = (command) => {
return JSON.stringify({
Name: "AAA",
Subject: "Math",
Day: "Thursday",
Parameters: { Data: command }
});
};
let ws = new WebSocket("ws://localhost:XXX");
ws.onopen = () => {
commands.forEach((command) => {
setTimeout(() => {
ws.send(getDataMethod(command));
}, 500);
});
};
ws.onmessage = (event) => {
if (event.data !== "Socket server connected") {
if (!event.data.includes("Error")) {
let myArray = ProcessElement(event.data);
console.log(myArray);
if (myArray.length > 0) commandResponse.push(myArray);
if (commandResponse.length === commands.length) {
console.log(commandResponse);
}
}
}
};
ws.onerror = (e) => {
console.log(`${i}: `, e);
};
}
};
Data can be retrieved, but I will get some error connections in between (err connection is refused / err connection is reset).
WebSocket is already in CLOSING or CLOSED state.
failed: Error in connection establishment: net::ERR_CONNECTION_REFUSED
failed: Error during WebSocket handshake: net::ERR_CONNECTION_RESET
Can i get some direction on how to fix it? Thank you

How to wait for .map() to finish and generate new keys in the array[index]

I'm trying to generate an array with values as follows:
{ name: 'John', age: 35, employer: 'ABC', paycheck: 5,000, last_paycheck: 4,900, change: 100 } // new array
with the initial values in the array as follow:
{ name: 'John', age: 35, employer: 'ABC' } //inital array
the function convertData() is handling all the array conversion.
async function convertData(data){
if(data.length === 0) return data;
// generates new array
const convertedDataArray = await data.map( async (row) =>{
let name = row.name
let paycheck = 0;
let last_paycheck = 0;
let change = 0;
const response = await axios.get('/getData', {params: {
name,
}});
let apiData = response.data.data;
if(apiData.length > 0){
let newData = apiData[0];
let oldData = apiData[1];
change = newData.payCheck - oldData.payCheck;
paycheck = newData.payCheck;
last_paycheck = oldData.payCheck;
}
console.log(apiData); // prints records up to 100 elements
return {...row, paycheck, last_paycheck, change };
});
console.log(convertedDataArray);// prints [Promise]
return Promise.all(convertedDataArray).then(() =>{
console.log(convertedDataArray); // prints [Promise]
return convertedDataArray;
});
};
where convertData() is called:
const response = await axios.get('/getEmployees',{params: {
token: id,
}});
const dataRows = response.data; //inital array
const tableRows = await convertData(dataRows);
return Promise.all(tableRows).then(() =>{
console.log(tableRows); // prints [Promise]
dispatch(setTableRows(tableRows));
});
I'm not sure why i keep getting Promise return I am still learning how to use promise correctly. Any help would be great, thank you in advance!
You should get a array of promises and use Promises.all to get all the data first.
Then use map() function to construct your data structure.
Example below:
async function convertData(data) {
try {
if (data.length === 0) return data;
const arrayOfPromises = data.map(row =>
axios.get("/getData", {
params: {
name: row.name,
},
})
);
const arrayOfData = await Promise.all(arrayOfPromises);
const convertedDataArray = arrayOfData.map((response, i) => {
const apiData = response.data.data;
let paycheck = 0;
let last_paycheck = 0;
let change = 0;
if (apiData.length > 0) {
const newData = apiData[0];
const oldData = apiData[1];
change = newData.payCheck - oldData.payCheck;
paycheck = newData.payCheck;
last_paycheck = oldData.payCheck;
}
return { ...data[i], paycheck, last_paycheck, change };
});
return convertedDataArray;
} catch (err) {
throw new Error(err);
}
}
(async function run() {
try {
const response = await axios.get("/getEmployees", {
params: {
token: id,
},
});
const dataRows = response.data;
const tableRows = await convertData(dataRows);
dispatch(setTableRows(tableRows));
} catch (err) {
console.log(err);
}
})();

Resources