how to run useEffect only twice - javascript

Here is My useEffect is going in Infinite loop, becouse checkimage value is changing becouse the value is assigned in fetch(), so anyone know how to solve it. I want to get varient data with image but I can't get it in first time.
help me if you can
Thank You
useEffect(() => {
fetch({ pagination });
}, [checkimage]);
const fetch = async (params = {}) => {
if (type == 'product') {
dispatch(await ProductService.getProduct(productId))
.then((res) => {
let variantsdatas = getImageArns(res.data.variants);
getImages(variantsdatas);
let record = [];
record.push(res.data)
setVarientsData(record)
})
.catch((err) => {});
} else {
dispatch(await ProductService.getProducts())
.then((res) => {
console.info({ 'res.data': res.data });
setVarientsData(res.data.products);
setPagination({
...params.pagination,
total: res.total_count,
});
})
.catch((err) => {});
}
};
const getImageArns = (variantsdatas) => {
const variantImageArns = [];
variantsdatas.forEach((variant, index) => {
variant[index] = variant.variantId;
if (variant.variantImagesListResponseDto.images.length > 0) {
let variantImageObj = {
variantId: variant.variantId,
arnUrl: variant.variantImagesListResponseDto.images[0].docUrl,
};
variantImageArns.push(variantImageObj);
}
});
// console.info('id', variantImageArns);
return variantImageArns;
};
const getImages = async (variantsdatas) => {
const images = [];
dispatch(await ProductVariantService.getImage(variantsdatas))
.then((res) => {
console.info(res.data.fileResponseDtoList);
let presignedURLs = {};
res.data.fileResponseDtoList.map(
(i) => (
(presignedURLs = {
variantId: i.variantId,
arnUrl: i.presignedURL,
}),
console.info(presignedURLs),
images.push(presignedURLs)
)
);
setcheckimage(images);
})
.catch((err) => {
console.info('Get Error District...');
});
};
var img = 'img';
const setVarientsData = (products) => {
let varients_array = [];
if (products.length > 0) {
products.forEach((product) => {
if (product.variants.length > 0) {
let product_varients = product.variants;
product_varients.forEach((varient) => {
for (var f = 0; f < checkimage.length; f++) {
if(checkimage[f].variantId == varient.variantId){
img = checkimage[f].arnUrl;
f = checkimage.length
}
else{
img = 'img2';
}
}
varients_array.push({
image: img,
variantId: varient.variantId,
productVariantName: varient.variantName,
productName: product.productName,
brand: '-',
sellerSku: varient.productVariantCode,
status: product.status,
category: product.subCategoryInfo.categoryInfo.categoryName,
subCategoryName: product.subCategoryInfo.subCategoryName,
state: '-',
market: '-',
mrp: varient.price.amount + ' ' + varient.price.currency,
sellingPrice: '-',
manufacturer_product_variant_code:
varient.manufacturerProductVariantCode,
product_varient_code: varient.azProductVariantLongCode,
hsnCode: varient.hsnCode,
});
});
}
});
}
setVarients(varients_array);
console.info('varients_array ====>>', {varients_array})
};
I think that if I stop to run blow code getImage function then I can get my result
am I right?
But I tried It too but is also not happening properly.

a quick and dirty fix could be to work with a counter.
and only run the fetch in the useEffect, when counter is 0.
have you tried that?

Related

Getting the same error: "Warning: Received NaN for the children attribute. If this is expected, cast the value to a string."

Tried fixing it multiple times and looked over it multiple times but keep on getting the same error: "react-dom.development.js:86 Warning: Received NaN for the children attribute. If this is expected, cast the value to a string."
Need help reviewing this code below and see why that error keeps on showing up
import React, {useState, useEffect} from "react";
function BlackjackGame() {
// useState will return a tuple where the first parameter ()
// ...is the current state of the deck. () allows us to update
// ...the state of the deck.
const [deckFilled, setDeckFilled] = useState(false);
// declaring a new state variable for the card deck
const [cardDeck, setCardDeck] = useState({});
// PLAYER :
// declaring a new state variable for the player
const [gamePlayer, setPlayer] = useState([]);
// declaring a new state variable that holds the player points
const [playerPoints, setPlayerPoints] = useState(0);
// new state variable for optional player points
const [optlPPt, setOptlPPt] = useState(0);
const [showOptlPPt, setShowOptlPPt] = useState(false);
// new state variable for the player cards
const [enablePlayerCards, setEnablePlayerCards] = useState(true);
// new state variable for the when the player is done with their round
const [endOfPlayerRound, setEndOfPlayerRound] = useState(false);
// new state variable for the player buy-in
let playerCurrentBuyIn = 5000;
const [playerBalance, setPlayerBalance] = useState(playerCurrentBuyIn);
// GAME :
// setting the variable for the bet
const[currBet, setBet] = useState(0);
// game round
let round = 3;
const [gameRound, setGameRound] = useState(round);
// game bet
const [placeGameBet, setPlaceGameBet] = useState(true);
// game message
const [msg, setMsg] = useState('How much are you betting?')
const [betButton, setBetButton] = useState(true);
const[forDouble, setForDouble] = useState(false);
const[savedGames, setSavedGames] = useState(false);
const[endOfGame, setEndOfGame] = useState(false);
const[results, setResults] = useState([]);
// DEALER :
// declaring a new state variable for the dealer
const [dealer, setDealer] = useState([]);
// declaring the state variable for that holds the dealer points
const [dealerPoints, setDealerPoints] = useState(0);
// new state variable for optional dealer points
const [optlDlrPt, setOptlDlrPt] = useState(0);
const [showOptlDlrPt, setShowOptlDlrPt] = useState(false);
// back of the dealers card
const [backOfDealersCard, setBackofDealersCard] = useState(false);
// variable for the Hit Button
let hitButton = enablePlayerCards === true && endOfPlayerRound === false && placeGameBet === false;
// variable for the stand button
let standButton = endOfPlayerRound === false && enablePlayerCards === true && placeGameBet === false;
// variable for the double button
let doubleButton = gamePlayer.length === 2 && endOfPlayerRound === false &&
placeGameBet === false && playerBalance >= currBet;
// passing an empty dependencies array to the useEffect hook...
// ...so it runs only when the component mounts
useEffect(() => {
// creating a new deck side effect
composeNewDeck();
window.addEventListener('beforeunload', (event) => {
save()
// cancel the event by the standard
event.preventDefault();
// return the value
return event.returnValue = 'Did you make up your mind?';
})
return() => {
window.removeEventListener('beforeunload', (event) => {
save()
// cancel the event by the standard
event.preventDefault();
// return the value
return event.returnValue = 'Did you make up your mind?';
})
}
}, )
useEffect(() => {
setPlayerPoints(() => {return 0})
setOptlPPt(() => {return 0})
gamePlayer.map((card) => (
card.value === 'Jack' || card.value === 'King' || card.value === 'Queen' ? (
setPlayerPoints((points) => { return points + 10}),
setOptlPPt((points) => { return points + 10})
):
card.value === 'Ace' ? (
setPlayerPoints((points) => { return points + 11}),
setOptlPPt((points) => { return points + 1}),
setShowOptlPPt(() => {return true})
):(
setPlayerPoints((points) => { return points + parseInt(card.value) }),
setOptlPPt((points) => { return points + parseInt(card.value)})
)
))
}, [gamePlayer])
useEffect(() => {
setDealerPoints(() => {return 0})
setOptlDlrPt(() => {return 0})
if (dealer.length === 2 && endOfPlayerRound === false) {
if (dealer[0].value === 'Jack' ||
dealer[0].value === 'King' ||
dealer[0].value === 'Queen' ) {
setDealerPoints((points) => { return points + 10})
setOptlDlrPt((points) => { return points + 10})
} else if (dealer[0].value === 'Ace') {
setDealerPoints((points) => { return points + 11})
setOptlDlrPt((points) => { return points + 1})
setShowOptlDlrPt(() => { return true})
} else {
setDealerPoints((points) => { return points + parseInt(dealer[0].value) })
setOptlDlrPt((points) => { return points + parseInt(dealer[0].value)})
}
} else {
dealer.map((card) => (
card.value === 'Jack' ||
card.value === 'King' ||
card.value === 'Queen' ? (
setDealerPoints((points) => { return points + 10}),
setOptlDlrPt((points) => { return points + 10})
):
card.value === 'Ace' ? (
setDealerPoints((points) => { return points + 11}),
setOptlDlrPt((points) => { return points + 1}),
setShowOptlDlrPt(() => {return true})
): (
setDealerPoints((points) => { return points + parseInt(card.value) }),
setOptlDlrPt((points) => { return points + parseInt(card.value)})
)
))
}
}, [dealer, endOfPlayerRound])
useEffect(() => {
if (playerPoints > 21 && optlPPt > 21) {
setEnablePlayerCards(() => {return false})
setMsg('Uh Oh...Looks like you lost');
setTimeout(() => {
dealerWon();
}, 2000);
} else if (playerPoints === 21 || optlPPt === 21) {
setMsg("Now you see...Blackjack!")
setEnablePlayerCards(() => {return false})
setTimeout(() => {
stand()
}, 2000);
} else {
forDouble === true && stand();
}
}, [playerPoints])
useEffect(() => {
if ( ((endOfPlayerRound === true && dealerPoints <= 16) ||
(dealerPoints > 21 && optlDlrPt <= 16)) && dealerPoints !== 0) {
setMsg("Computers turn");
draw(false, drawFirstCard);
} else if (endOfPlayerRound === true && dealerPoints !== 0) {
let comparePlayersPoint;
let compareDealerPoint;
if (playerPoints > 21 && (optlPPt > 0 && optlPPt <= 21) ) {
comparePlayersPoint = optlPPt;
} else {
comparePlayersPoint = playerPoints;
}
if( dealerPoints > 21 && optlDlrPt > 21){
compareDealerPoint = 0;
} else if (dealerPoints > 21 && (optlDlrPt > 0 && optlDlrPt <= 21)) {
compareDealerPoint = optlDlrPt;
} else if (dealerPoints <= 21) {
compareDealerPoint = dealerPoints;
}
if( (21 - comparePlayersPoint) < (21 - compareDealerPoint) ) {
setMsg("You won")
setTimeout(() => {
playerWon();
}, 2000);
} else if ((21 - comparePlayersPoint) > (21 - compareDealerPoint)){
setMsg("Computer won")
setTimeout(() => {
dealerWon();
}, 2000);
} else {
setMsg("Draw")
setTimeout(() => {
noWinner();
}, 2000);
}
}
}, [dealerPoints])
useEffect(() => {
if (placeGameBet === true) {
setMsg("How much are you betting?");
setBetButton(true);
}
}, [placeGameBet])
useEffect(() => {
if ( gameRound > 5 ) {
endGame();
} else if (gameRound !== 1 && savedGames === false) {
nextRound();
} else {
setSavedGames(false);
}
}, [gameRound])
// calling the Deck Of Cards API to fecth the cards
const composeNewDeck = () => {
fetch(deckOfCardsLink + shuffleDeckOfCards + deckAmt, {
method: 'GET',
headers: {
Accept: 'application/json',
'Content-Type': 'application/json',
},
})
.then(response => response.json())
.then(responseData => {
setDeckFilled(() => { return true; })
setCardDeck( () => { return {...responseData}; })
})
.catch(err => {
console.log('error : ' + err);
});
}
// calling the Deck Of Cards API to draw a card
const draw = (forPlayers, amtOfCards) => {
fetch(deckOfCardsLink + cardDeck.deck_id + amtOfCards, {
method: 'GET',
headers: {
Accept: 'application/json',
'Content-Type': 'application/json',
},
})
.then(response => response.json())
.then(responseData => {
if (forPlayers === true) {
setPlayer((playerHand) => { return [...playerHand, ...responseData.cards]; })
} else {
setDealer((dealerHand) => { return [...dealerHand, ...responseData.cards]; })
}
})
.catch(err => {
console.log('error : ' + err);
});
}
// calling the Deck Of Cards API to shuffle the card deck
const shuffleDeck = (deckId) => {
fetch(deckOfCardsLink + deckId + reShuffleDeckOfCard, {
method: 'GET',
headers: {
Accept: 'application/json',
'Content-Type': 'application/json',
},
})
.then(response => response.json())
.then(responseData => {
setDeckFilled(() => { return true; })
setCardDeck( () => { return {...responseData}; })
})
.catch(err => {
console.log('error : ' + err);
});
}
const stand = () => {
setBackofDealersCard(() => {return true})
setTimeout(() => {
setEndOfPlayerRound(() => {return true})
setEnablePlayerCards(() => {return false})
}, 250);
}
const double = () => {
setForDouble(true);
setMsg("Going for double!")
setPlayerBalance((balance) => {return balance - currBet})
setBet((bet) => {return bet+bet})
draw(true, drawFirstCard);
}
const startRound = () => {
setEndOfPlayerRound(false);
setEnablePlayerCards(true);
setPlaceGameBet(false);
setBetButton(false);
setMsg("Your turn");
if (deckFilled === true) {
draw(true, drawSecondCard);
draw(false, drawSecondCard);
}
}
const bet = (amount) => {
if (playerBalance - amount >= 0) {
setPlayerBalance((balance) => { return balance - amount});
setBet((bet) => {return bet + amount})
}
}
const playerWon = () => {
setPlayerBalance((balance) => {return balance + (currBet * 1.5)})
setGameRound((round) => {return round + 1});
}
const dealerWon = () => {
setGameRound((round) => {return round + 1});
}
const noWinner = () => {
setPlayerBalance((balance) => {return balance + currBet})
setGameRound((round) => {return round + 1});
}
const nextRound = () => {
setBackofDealersCard(false);
setForDouble(false);
setShowOptlDlrPt(false);
setShowOptlPPt(false);
setPlayerPoints(0);
setOptlPPt(0);
setDealerPoints(0);
setOptlDlrPt(0);
setPlaceGameBet(true);
setBetButton(true);
setBet(0);
setPlayer([]);
setDealer([]);
}
const endGame = () => {
setEndOfGame(true);
setBet(0);
setMsg("Game Over");
let rank = JSON.parse(localStorage.getItem("rank"));
if( rank === undefined || rank === null) {
localStorage.setItem("rank", JSON.stringify({
points: [playerBalance]
}))
} else {
let sortedRank = rank.points.sort(function(a, b) {
return b - a;
})
if (sortedRank.length<=2) {
setResults([...sortedRank])
} else {
setResults([sortedRank[0],sortedRank[1],sortedRank[2]])
}
localStorage.setItem("rank", JSON.stringify({
points: [...rank.points, playerBalance]
}))
}
}
const reset = () => {
setEndOfGame(false);
setDeckFilled(false);
shuffleDeck(cardDeck.deck_id);
nextRound();
setGameRound(3);
setPlayerBalance(5000);
}
const save = () => {
localStorage.setItem("savedGame", JSON.stringify(
{
deckFilled: deckFilled,
cardDeck: cardDeck,
gamePlayer: gamePlayer,
dealer: dealer,
playerPoints: playerPoints,
dealerPoints: dealerPoints,
optlPPt: optlPPt,
showOptlPPt: showOptlPPt,
optlDlrPt: optlDlrPt,
showOptlDlrPt: showOptlDlrPt,
enablePlayerCards: enablePlayerCards,
endOfPlayerRound: endOfPlayerRound,
playerBalance: playerBalance,
currBet: currBet,
backOfDealersCard: backOfDealersCard,
gameRound: gameRound,
placeGameBet: placeGameBet,
msg: msg,
betButton: betButton,
forDouble: forDouble,
}
));
}
const load = () => {
setSavedGames(true);
let gameSave = JSON.parse(localStorage.getItem('savedGame'));
if (gameSave !== undefined) {
setCardDeck(gameSave.cardDeck);
setPlayer(gameSave.gamePlayer);
setDealer(gameSave.dealer);
setPlayerPoints(gameSave.playerPoints);
setDealerPoints(gameSave.dealerPoints);
setOptlPPt(gameSave.optlPPt);
setShowOptlPPt(gameSave.showOptlPPt);
setOptlDlrPt(gameSave.optlDlrPt);
setShowOptlDlrPt(gameSave.showOptlDlrPt);
setEnablePlayerCards(gameSave.enablePlayerCards);
setEndOfPlayerRound(gameSave.endOfPlayerRound);
setPlayerBalance(gameSave.playerBalance);
setBet(gameSave.currBet);
setBackofDealersCard(gameSave.backOfDealersCard);
setGameRound(gameSave.gameRound);
setPlaceGameBet(gameSave.placeGameBet);
setMsg(gameSave.msg);
setBetButton(gameSave.betButton);
setForDouble(gameSave.forDouble);
setDeckFilled(gameSave.deckFilled);
}
}

Run async/await function inside a reduce Javascript [duplicate]

This question already has answers here:
JavaScript array .reduce with async/await
(11 answers)
Closed 6 months ago.
I need to fetch values from another API using the guid inside this particular array, then group them together (hence I used reduce Javascript in this case)
However, I could not get those values sumEstimatedHours and sumWorkedHours as expected. Can someone suggest a method please?
export const groupProjectsByPM = (listOfProjects) => {
const dir = "./json";
const estimatedHours = fs.existsSync(dir)
? JSON.parse(fs.readFileSync("./json/phases.json", "utf-8"))
: null;
let sumWorkedHours, sumEstimatedHours;
const groupedProjects = listOfProjects?.reduce(
(
group,
{
guid,
projectOwner: { name: POName },
name,
customer: { name: customerName },
deadline,
calculatedCompletionPercentage,
}
) => {
listOfProjects.map(async (element, index) => {
// const element = listOfProjects[index];
sumWorkedHours = await getWorkhoursByProject(element?.guid).then(
(res) => {
return res.reduce((acc, cur) => {
return acc + cur.quantity;
}, 0);
}
);
const filteredEstimatedHours = estimatedHours.filter(
(item) => item.project.guid === element.guid
);
sumEstimatedHours = filteredEstimatedHours.reduce((acc, cur) => {
return acc + cur.workHoursEstimate;
}, 0);
group[POName] = group[POName] || [];
group[POName].push({
guid,
name,
POName,
customerName,
deadline,
calculatedCompletionPercentage,
sumEstimatedHours,
sumWorkedHours,
});
return group;
});
return group;
},
[]
);
return groupedProjects;
};
here is an example of async/await inside reduce:
let's assume that we have an array of numbers
const arrayOfNumbers = [2,4,5,7,6,1];
We are going to sum them using reduce function:
const sumReducer = async () => {
const sum = await arrayOfNumbers.reduce(async (promisedSum, num) => {
const sumAcc = await promisedSum
// any promised function can be called here..
return sumAcc + num
}, 0)
console.log(sum)
}
So the trick is to remember to await the accumulator inside the reduce function
export const groupProjectsByPM = async (listOfProjects) => {
const dir = "./json";
const estimatedHours = fs.existsSync(dir)
? JSON.parse(fs.readFileSync("./json/phases.json", "utf-8"))
: null;
let sumWorkedHours, sumEstimatedHours;
const groupedProjects = await listOfProjects?.reduce(
async (
promisedGroup,
{
guid,
projectOwner: { name: POName },
name,
customer: { name: customerName },
deadline,
calculatedCompletionPercentage,
}
) => {
listOfProjects.map(async (element, index) => {
//accumulator in your case is group
const group = await promisedGroup;
// const element = listOfProjects[index];
sumWorkedHours = await getWorkhoursByProject(element?.guid).then(
(res) => {
return res.reduce((acc, cur) => {
return acc + cur.quantity;
}, 0);
}
);
const filteredEstimatedHours = estimatedHours.filter(
(item) => item.project.guid === element.guid
);
sumEstimatedHours = filteredEstimatedHours.reduce((acc, cur) => {
return acc + cur.workHoursEstimate;
}, 0);
group[POName] = group[POName] || [];
group[POName].push({
guid,
name,
POName,
customerName,
deadline,
calculatedCompletionPercentage,
sumEstimatedHours,
sumWorkedHours,
});
return group;
});
return group;
},
[]
);
return groupedProjects;
};
Best of luck ...

Is there a better way to achieve this?

I am using React. On click of a button, the following function is executed:
const completeTaskHandler = (idValue) => {
setData((prevData) => {
const updatedData = [...prevData];
const updatedItem = updatedData.filter((ele) => ele.id === idValue)[0];
updatedItem.completed = true;
const newData = updatedData.filter((ele) => ele !== updatedItem);
newData.unshift(updatedItem);
return newData;
});
};
My data is an array of objects like this:
[{userId: 1, id: 2, title: "task 1", completed: true}, .....].
Basically I want to move the updated item to the start of the array. Is there any better solution for this?
updatedItem should not be mutated. And this string const newData = updatedData.filter((ele) => ele !== updatedItem); is not fine. You can do it like this :
const completeTaskHandler = (idValue) => {
setData((prevData) => {
const targetItem = prevData.find((ele) => ele.id === idValue);
const updatedItem = { ...targetItem, completed: true };
const filteredData = prevData.filter((ele) => ele.id !== idValue);
return [updatedItem, ...filteredData];
});
};
Even better to reducing an extra filter:
const completeTaskHandler = (idValue) => {
setData((prevData) => {
const targetIndex = prevData.findIndex((ele) => ele.id === idValue);
return [{ ...prevData[targetIndex], completed: true }].concat(prevData.slice(0, targetIndex + 1)) .concat(
prevData.slice(targetIndex + 1)
)
});
};
First find index of updated element using Array.findIndex(), then remove the same element using Array.splice() and add it to front of the array.
const completeTaskHandler = (idValue) => {
setData((prevData) => {
const updatedData = [...prevData];
const index = updatedData.findIndex(obj => obj.id === idValue);
const [updatedItem] = updatedData.splice(index, 1);
updatedItem.completed = true;
updatedData.unshift(updatedItem);
return updatedData;
});
};
The simplest one with only one forEach.
const completeTaskHandler = idValue => {
setData(prevData => {
let updatedItem = {}, newData = [];
prevData.forEach((ele) => {
if (ele.id === idValue) {
updatedItem = ele;
updatedItem.completed = true;
} else {
newData.push(ele);
}
});
newData.unshift(updatedItem);
return newData;
});
};

How to call aysnc function getAffiliatesCodes() inside other async function

this is the first function , i have this function getAffliateCodesAsync() my requirement is to call this method from inside other function (function -2 >> generateCriBodyWithCreParameter(..))
and pass the returning value of >>(function-1) getAffliateCodesAsync(), into the third function and use that value in (function -3) checkLessorMagnitudeCode(..) and use the returning value of function-2 in function-3 at place where codeList is used, Please help
//function-1.
async function getAffliateCodesAsync(){
console.debug("==AFFILIATE_CODES==");
const ApplicationParameter = loopback.getModel('ApplicationParameter');
const applicationParamFieldValue = await ApplicationParameter.find({
where: {
fieldName: 'AFFILIATE_CODES'
},
fields: ['fieldValue']
});
return (applicationParamFieldValue.length)? applicationParamFieldValue.map(entity => String(entity['fieldValue'])):[];
}
//2.function-2
const generateCriBodyWithCreParameter = (positions, lotNumber, cutOffDate) => {
const CreParameter = loopback.getModel('CreParameter');
let creId = 1;
const positionData = [];
const content = [];
return CreParameter.find()
.then((creParameterList) => {
const promises = positions.map((position) => {
const cutOffDatePreviousMonth = getCutOffDatePreviousMonth(position.accountingDate);
return positionNativeProvider.getPositionInformationForPreviousCutOffDateForCriApf(
position, cutOffDatePreviousMonth)
.then((positionRetrieved) => {
const positionLowerCase = _.mapKeys(position, (value, key) => _.toLower(key));
const creParameters = _.filter(creParameterList, {
flowType: 'MI',
event: 'POSITION',
liabilityAmortizationMethod: position.liabilityAmortizationMethod
});
for (const creParameter of creParameters) {
const atollAmountValue = getAtollAmountValue(positionLowerCase, creParameter);
if (atollAmountValue && matchSigns(atollAmountValue, creParameter.amountSign)) {
const lineGenerated = checkContractLegalStatusForCri(position, creParameter,
atollAmountValue, content, creId, lotNumber, cutOffDate, positionRetrieved);
//No Line is generated in this case so the creId must not incremente
if (lineGenerated !== -1) {
positionData.push({
positionId: position.id,
creId
});
creId++;
}
}
}
});
});
return Promise.all(promises)
.then(() => {
return {
contentCreBody: content.join('\n'),
positionData
};
});
});
};
//function -3
const checkLessorMagnitudeCode = (lessorMagnitudeCode,codeList=[]) => {
if (!lessorMagnitudeCode) return false;
if (_.size(lessorMagnitudeCode) === 5 &&
(_.startsWith(lessorMagnitudeCode, 'S') || _.startsWith(lessorMagnitudeCode, 'T'))
&& codeList.includes(lessorMagnitudeCode)) {
return true;
}
return false;
};
//above codelist where I want to use the returning value

How to measure the time of several calls of async function

I have a problem with understanding how do async functions in js work. So I need to call async function for 5 times and measure the duration of every execution. In the end I should have an array with 5 time values.
I have smth like this
for (let i = 0; i < 5; i++) {
const run = async () => {
await test(thisTest, filename, unitTestDict);
};
measure(run).then(report => {
// inspect
const {tSyncOnly, tSyncAsync} = report;
// array.push(tSyncAsync)
console.log(`∑ = ${tSyncAsync}ms \t`);
}).catch(e => {
console.error(e)
});
}
Here I found the realization of time measure function:
class Stack {
constructor() {
this._array = []
}
push(x) {
return this._array.push(x)
}
peek() {
return this._array[this._array.length - 1]
}
pop() {
return this._array.pop()
}
get is_not_empty() {
return this._array.length > 0
}
}
class Timer {
constructor() {
this._records = new Map
/* of {start:number, end:number} */
}
starts(scope) {
const detail =
this._records.set(scope, {
start: this.timestamp(),
end: -1,
})
}
ends(scope) {
this._records.get(scope).end = this.timestamp()
}
timestamp() {
return performance.now()
}
timediff(t0, t1) {
return Math.abs(t0 - t1)
}
report(scopes, detail) {
let tSyncOnly = 0;
let tSyncAsync = 0;
for (const [scope, {start, end}] of this._records)
if (scopes.has(scope))
if (~end) {
tSyncOnly += end - start;
tSyncAsync += end - start;
const {type, offset} = detail.get(scope);
if (type === "Timeout")
tSyncAsync += offset;
}
return {tSyncOnly, tSyncAsync}
}
}
async function measure(asyncFn) {
const stack = new Stack;
const scopes = new Set;
const timer = new Timer;
const detail = new Map;
const hook = createHook({
init(scope, type, parent, resource) {
if (type === 'TIMERWRAP') return;
scopes.add(scope);
detail.set(scope, {
type: type,
offset: type === 'Timeout' ? resource._idleTimeout : 0
})
},
before(scope) {
if (stack.is_not_empty) timer.ends(stack.peek());
stack.push(scope);
timer.starts(scope)
},
after() {
timer.ends(stack.pop())
}
});
return await new Promise(r => {
hook.enable();
setTimeout(() => {
asyncFn()
.then(() => hook.disable())
.then(() => r(timer.report(scopes, detail)))
.catch(console.error)
}, 1)
})
}
I can call it inside the loop and get console.log with time for every iteration:
measure(run).then(report => {
// inspect
const {tSyncOnly, tSyncAsync} = report;
// array.push(tSyncAsync)
console.log(`∑ = ${tSyncAsync}ms \t`);
}).catch(e => {
console.error(e)
});
But when I try to push this console values to array, nothing comes out, the array remains empty. Is there a way to fill it in?

Categories

Resources