I have this scheduled function that :
read 1 document from collection
data: [
{
'field1' : 123,
'field2' : 456
},
{
'field1' : 123,
'field2' : 456
}
...
]
loop on all data array
read new value from rest api call
update the value of data array in firestore
NOTE from firebase function console log I have the log 'field updated ...' after the log 'firebase document updated ...', I think because the request is not sync
const functions = require('firebase-functions');
const admin = require('firebase-admin');
const db = admin.firestore();
const fetch = require('node-fetch');
var request = require("request");
const { Headers } = fetch;
exports.onStatisticUpdated = functions.region('europe-west1')
.runWith({
timeoutSeconds: 300,
})
.pubsub.schedule('every 60 minutes')
.onRun(async context => {
const doc = await admin
.firestore()
.collection('collection')
.doc('1234')
.get();
if (doc.exists) {
for (let i = 0; i < doc.data().data.length; i++) {
let myFirebaseData = doc.data().data[i];
var options = {
method: 'GET',
url: 'https://xyz....',
qs: { abcd: 'value' },
headers: {
'x-xxxx-host': 'v1....',
'x-xxxx-key': 'xxxxxxxxxxxx'
}
}
request(options, function (error, response, body) {
if (error) throw new Error(error);
var json = JSON.parse(body);
if (json['response'].length > 0) {
console.log('field updated ...');
myFirebaseData.field1 = json['response'][0].value1
myFirebaseData.field2 = json['response'][0].value2
};
});
}
// myFirebaseData is not updated at this time with new value filled by rest api !!!
console.log(' firebase document updated ...');
await admin
.firestore()
.collection('collection')
.doc('1234')
.update({
data: doc.data(),
});
}
});
question : how i can store the final document with new values filled by the rest api ?
In Cloud Functions you need to manage asynchronous method calls via Promises (more details here in the doc). request supports callback interfaces natively but does not return a Promise.
You should use another library, like axios. In addition, since you want to execute a variable number of asynchronous Rest API calls in parallel, you need to use Promise.all().
Now, what is not clear to me in your code is how do you build the object used to update the 1234 document. I your current code, in the for (let i = 0; i < doc.data().data.length; i++) {}) loop you are actually overwriting the field1 and field2 properties of the myFirebaseData again and again...
Therefore you will find below the code structure/pattern that I think is correct and if it is not the case, just add a comment to this answer and we can fine tune the answer according to the extra details you will share.
exports.onStatisticUpdated = functions.region('europe-west1')
.runWith({
timeoutSeconds: 300,
})
.pubsub.schedule('every 60 minutes')
.onRun(async context => {
const doc = await admin
.firestore()
.collection('collection')
.doc('1234')
.get();
if (doc.exists) {
const promises = [];
for (let i = 0; i < doc.data().data.length; i++) {
let myFirebaseData = doc.data().data[i];
var options = {
method: 'get',
url: 'https://xyz....',
params: { abcd: 'value' },
headers: {
'x-xxxx-host': 'v1....',
'x-xxxx-key': 'xxxxxxxxxxxx'
}
}
promises.push(axios(options))
}
apiResponsesArray = await Promise.all(promises);
const updateObject = {};
apiResponsesArray.forEach((resp, index) => {
// THIS ENTIRE BLOCK NEEDS TO BE ADAPTED!!
// I'M JUST MAKING ASSUMPTIONS...
const responseData = resp.data;
updateObject["field1" + index] = responseData.value1;
updateObject["field2" + index] = responseData.value2;
})
console.log(updateObject)
console.log(' firebase document updated ...');
await admin
.firestore()
.collection('collection')
.doc('1234')
.update({
data: updateObject
});
return null; // IMPORTANT!!! see the link to the doc above
}
});
I'm trying to transfer a BEP-20 token on BSC from one Wallet to Another. I actually had it at one point and somehow messed up while doing code cleanup. Anway, I need some help. When I send my transaction I never get a confirmation.
I get a hash for example : 0xd18ee37686b00d45edb9974d8a119534f3403052e3ed4908ac8ca80bde385416
But it never goes anywhere. I've beat my head on the wall with this for two days, any help would be greatly appreciated. - Note Endpoint and Private Key are fake
// Ethereum javascript libraries needed
var Web3 = require('web3')
var Tx = require("ethereumjs-tx").Transaction;
const Common = require('ethereumjs-common');
const mysql = require('mysql');
//KLUV Contract Address KLUV - BSC
const _ContractAddress_ = '0x3A68A9Cd188C324a45c06866eFD1C79605B66827';
const _ContractABI_ = JSON.parse('[{"inputs":[],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"spender","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"Approval","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"Transfer","type":"event"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"spender","type":"address"}],"name":"allowance","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"approve","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"decimals","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"subtractedValue","type":"uint256"}],"name":"decreaseAllowance","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"getunlockedAfter","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"addedValue","type":"uint256"}],"name":"increaseAllowance","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"lockedPeriodOver","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"symbol","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"recipient","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"transfer","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"sender","type":"address"},{"internalType":"address","name":"recipient","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"transferFrom","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"withdrawLockedTokens","outputs":[],"stateMutability":"nonpayable","type":"function"},{"stateMutability":"payable","type":"receive"}]');
//To Wallet Address
const _ToWalletAddress_ = '0x76D52CF51D9a4B8C84Bf01b7AA3f801c52A328D8';
//My MetaMask Wallet
const _FromWalletAddress_ = '0xDeBCBca7f21aB70DA4e7860a112FEB3d8Fd04db5';
//My MetaMask Private Key
const _FromWalletPrivateKey_ = 'f777980edfc1c92446XXXXXXXXXXXXXXXe615ffcccc0744f0a4054c8f924773d';
//Node URL
const BSCNode = 'https://nd-098-532-742.p2pify.com/super_secret_address';
const web3 = new Web3(new Web3.providers.HttpProvider(BSCNode));
const main = async () => {
console.log(`web3 version: ${web3.version}`)
// Who holds the token now?
var senderWalletAddress = _FromWalletAddress_;
// Who are we trying to send this token to?
var receiverWalletAddress = _ToWalletAddress_;
// The address of the contract which created MFIL
var contractAddress = _ContractAddress_;
var contract = new web3.eth.Contract(_ContractABI_, contractAddress, {
from: senderWalletAddress
});
// How many tokens do I have before sending?
var balance = await contract.methods.balanceOf(senderWalletAddress).call();
console.log(`Balance before send: ${balance} sKLUV\n------------------------`);
// Use Gwei for the unit of gas price
var gasPriceGwei = 5;
var gasLimit = 5000000;
// .00000001 KLUV
var transferAmount = 1;
// Determine the nonce - This isn't always good, you need to keep track of it
var count = await web3.eth.getTransactionCount(senderWalletAddress);
console.log(`num transactions so far: ${count}`);
/* Override count - especially if testing */
count = 77;
var rawTransaction = {
"from": senderWalletAddress,
"nonce": "0x" + count.toString(16),
"gasPrice": web3.utils.toHex(gasPriceGwei * 1e9),
"gasLimit": web3.utils.toHex(gasLimit),
"to": contractAddress,
"value": "0x0",
"chainId": 56,
"data": contract.methods.transfer(receiverWalletAddress, transferAmount).encodeABI(),
};
console.log(`Raw of Transaction: \n${JSON.stringify(rawTransaction, null, '\t')}\n------------------------`);
// Create Buffer containing hex of private key
var privKey = new Buffer.from(_FromWalletPrivateKey_, 'hex');
/* Define What Block Chain we're using */
const chain = Common.default.forCustomChain(
'mainnet', {
name: 'bnb',
networkId: 56,
chainId: 56
},
'petersburg'
)
/* generate transaction including my block chain */
var tx = new Tx(rawTransaction, {common: chain});
/* sign the transaction with my buffered private key */
tx.sign(privKey);
/* Serialize the result */
var serializedTx = tx.serialize();
/* Get Ready to send */
console.log(`Attempting to send signed tx: ${serializedTx.toString('hex')}\n------------------------`);
/* Limit the number of confirms we're looking for */
let numberOfConfirms = 5;
web3.eth.transactionConfirmationBlocks = numberOfConfirms;
/* Use Event Method so we can see where things are hanging up */
web3.eth.sendSignedTransaction('0x' + serializedTx.toString('hex'))
.on("sending", (payload) => {
console.log('sending ');
console.log(payload);
})
.on("sent", (payload) => {
console.log('Sent Payload');
console.log(payload);
})
.on('transactionHash', (transactionHash) => {
console.log('Received Transaction hash');
console.log(transactionHash);
})
.on("receipt", (receipt) => {
console.log('Received Receipt');
console.log(`Receipt info: \n${JSON.stringify(receipt, null, '\t')}\n------------------------`);
})
.on("confirmation", (confNumber, receipt, latestBlockHash) => {
console.log('Received Confirmation ', confNumber);
if (confNumber == numberOfConfirms) {
// The balance may not be updated yet, but let's check
contract.methods.balanceOf(senderWalletAddress).call().then((balance) => {
console.log(`Balance after send: ${balance} sKLUV`);
});
}
console.log(confNumber, receipt, latestBlockHash);
})
.on('error', err => {
console.log('Error Sending Transaction');
console.log(err.message);
}).catch(reason => {
console.log('Promise failed in catch');
console.log(reason);
});
};
main();
the only thing I see chainId in rawTransaction is not in hex format. should be
"chainId":web3.utils.toHex(56)
Hello so a little bit of background.
I created a function in JS that fetches some data(multiple objects that can change in number every time I fetch the data ad example : fetch1: I get 3 obj | fetch2: I get 1 obj, I CAN NOT GET 0 obj ) from a website every minute, processes that data, and then sends it to the cloud firestore. The problem is that after the upload of the data, the doc and the collection get deleted without any reason at all and I don't understand what is happening.
I tried to search online but I could not find a fix.
Can anyone give me a hint of what is happening ?
This is the function in JS
import functions = require("firebase-functions");
import admin = require("firebase-admin");
admin.initializeApp();
const database = admin.firestore();
import https = require("https");
let finalData: { [x: string]: any; }[] = [];
const page = 1;
const fiat = "";
const tradeType = "";
const asset = "";
const payTypes = [""];
const baseObj = {
page,
rows: ,
publisherType: ,
asset,
tradeType,
fiat,
payTypes,
};
const stringData = JSON.stringify(baseObj);
const options = {
hostname: "",
port: ,
path: "",
method: "",
headers: {
"Content-Type": "application/json",
"Content-Length": stringData.length,
},
};
const req = https.request(options, (res: any) => {
finalData = [];
let output = "";
res.on("data", (d: string) => {
output += d;
});
res.on("end", () => {
try {
const jsonOuput = JSON.parse(output);
const allData = jsonOuput["data"];
for (let i = 0; i < allData.length; i++) {
let payTypesz = "";
for (let y = 0; y < allData[i]["adv"]["tradeMethods"].length; y++) {
payTypesz += allData[i]["adv"]["tradeMethods"][y]["payType"];
if (y < allData[i]["adv"]["tradeMethods"].length - 1) {
payTypesz += ", ";
}
}
const obj = {
tradeType: allData[i]["adv"]["tradeType"],
asset: allData[i]["adv"]["asset"],
fiatUnit: allData[i]["adv"]["fiatUnit"],
price: allData[i]["adv"]["price"],
surplusAmount: allData[i]["adv"]["surplusAmount"],
maxSingleTransAmount: allData[i]["adv"]["maxSingleTransAmount"],
minSingleTransAmount: allData[i]["adv"]["minSingleTransAmount"],
nickName: allData[i]["advertiser"]["nickName"],
monthOrderCount: allData[i]["advertiser"]["monthOrderCount"],
monthFinishRate: allData[i]["advertiser"]["monthFinishRate"],
advConfirmTime: allData[i]["advertiser"]["advConfirmTime"],
payTypes: payTypesz,
position: 0,
};
finalData.push(obj);
}
console.log(finalData);
} catch (e) {
console.log(e);
}
});
});
exports.scheduledFunction = functions.pubsub
.schedule("* * * * *")
.onRun((context: any) => {
req.write(stringData);
req.end();
for (let i = 0; i < finalData.length; i++) {
database.doc("/$i")
.set({
"tradeType": finalData[i]["tradeType"],
"asset": finalData[i]["asset"],
"fiatUnit": finalData[i]["fiatUnit"],
"price": finalData[i]["price"],
"surplusAmount": finalData[i]["surplusAmount"],
"maxSingleTransAmount": finalData[i]["maxSingleTransAmount"],
"minSingleTransAmount": finalData[i]["minSingleTransAmount"],
"nickName": finalData[i]["nickName"],
"monthOrderCount": finalData[i]["monthOrderCount"],
"monthFinishRate": finalData[i]["monthFinishRate"],
"advConfirmTime": finalData[i]["advConfirmTime"],
"payTypes": finalData[i]["payTypes"],
"position": finalData[i]["position"],
});
}
return console.log("Succes Upload of the data ");
});
// # sourceMappingURL=index.js.map
This is the setup of the DB.
By default https for Node.js does not return Promises, therefore it can be cumbersome to correctly manage the life cycle of your Cloud Function.
I would suggest you use the axios library and refactor your code as follows, using a batched write to write to Firestore:
exports.scheduledFunction = functions.pubsub
.schedule("* * * * *")
.onRun(async (context: any) => { // <=== See async keyword here
try {
const httpCallResponse = await axios.get(...); // I let you adapt the code, including the URL to call, according to the axios doc
const finalData = ... // Again, it's up to you to work out the value based on httpCallResponse
const batch = database.batch();
for (let i = 0; i < finalData.length; i++) {
batch.set(database.doc(i.toString(10)),
{
"tradeType": finalData[i]["tradeType"],
"asset": finalData[i]["asset"],
"fiatUnit": finalData[i]["fiatUnit"],
"price": finalData[i]["price"],
"surplusAmount": finalData[i]["surplusAmount"],
"maxSingleTransAmount": finalData[i]["maxSingleTransAmount"],
"minSingleTransAmount": finalData[i]["minSingleTransAmount"],
"nickName": finalData[i]["nickName"],
"monthOrderCount": finalData[i]["monthOrderCount"],
"monthFinishRate": finalData[i]["monthFinishRate"],
"advConfirmTime": finalData[i]["advConfirmTime"],
"payTypes": finalData[i]["payTypes"],
"position": finalData[i]["position"],
});
}
await batch.commit();
console.log("Succes Upload of the data ");
return null;
} catch (error) {
console.log(error);
return true;
}
});
Extra Note: Note that with your code you create monotonically increasing IDs and that could be a problem.
Path 1 - Match_Creator/cricket/matchList;
Path 2 - Match_Creator/cricket/completedMatchList;
I have a collection called matchList (Path 1) In which i am having a doc called c434108.
Now I want to move this doc(c434108) to Path 2;
/* eslint-disable promise/catch-or-return */
const functions = require("firebase-functions");
const admin = require("firebase-admin");
const { db } = require("./db/index");
const createCompletedMatchListDoc = (request, response) => {
completedMatchDocsData();
};
function completedMatchDocsData() {
createNewCompletedMatchDocs()
}
function getOldCompletedMatchDocs(){
var completedMatchesRef = db
.collection("Match_Creator")
.doc("cricket")
.collection("matchList");
var completedMatchDocData;
var completedMatchDataArr = [];
return new Promise(resolve => {
let query = completedMatchesRef
.where("status", "==", "live")
.get()
.then(snapshot => {
// eslint-disable-next-line promise/always-return
if (snapshot.empty) {
console.log("No matching documents.");
return;
}
snapshot.forEach(doc => {
completedMatchDocData = doc.data();
completedMatchDataArr.push(completedMatchDocData);
resolve(completedMatchDataArr);
});
console.log("sarang", completedMatchDataArr[2]);
})
.catch(err => {
console.log("Error getting documents", err);
});
});
}
const createNewCompletedMatchDocs = (async(change, context) => {
let completedMatchData = await getOldCompletedMatchDocs();
console.log('aman', completedMatchData[1]);
const newValue = change.after.data();
const previousValue = change.before.data();
const st1 =newValue.status;
const st2 = previousValue.status;
console.log('I am a log entry' + st1 + ' ' + st2);
var data = completedMatchData[0];
return db.collection('Match_Creator').doc('cricket').collection('completedMatchList').add(data)
.catch(error => {
console.log('Error writting document: ' + error);
return false;
});
})
module.exports = createCompletedMatchListDoc;
And After copy this doc(c434108) i want to delete this doc(c434108) from path 1.
And My index.js file is:
const functions = require("firebase-functions");
const admin = require("firebase-admin");
const storeMatchData = require("./liveScoring");
const createCompletedMatchListDoc = require("./completedMatchList");
var http = require("https");
module.exports = {
liveScoring: functions.https.onRequest(storeMatchData),
createCompletedMatchListDoc: functions.https.onRequest(
createCompletedMatchListDoc
)
};
I am able to solve my problem.
This is my completeMatchList.js file
/* eslint-disable promise/catch-or-return */
const functions = require("firebase-functions");
const admin = require("firebase-admin");
const { db } = require("./db/index");
const createCompletedMatchListDoc = (request, response) => {
completedMatchDocsData();
};
function completedMatchDocsData() {
setNewCompletedMatchDocs()
}
function getOldCompletedMatchDocs(){
var completedMatchesRef = db
.collection("Match_Creator")
.doc("cricket")
.collection("matchList");
var completedMatchDocData;
var completedMatchDataArr = [];
return new Promise(resolve => {
let query = completedMatchesRef
.where("status", "==", "live")
.get()
.then(snapshot => {
// eslint-disable-next-line promise/always-return
if (snapshot.empty) {
console.log("No matching documents.");
return;
}
snapshot.forEach(doc => {
// completedMatchDocData = doc.data();
completedMatchDocData = {
docId: "",
docData: ""
}
completedMatchDocData.docId = doc.id;
completedMatchDocData.docData = doc.data();
completedMatchDataArr.push(completedMatchDocData);
resolve(completedMatchDataArr); // Here i am getting the data and pushing it in array
});
console.log("sarang", completedMatchDataArr);
})
.catch(err => {
console.log("Error getting documents", err);
});
});
}
const setNewCompletedMatchDocs = (async () => {
let getCompletedMatchData = await getOldCompletedMatchDocs();
// console.log("balram", getCompletedMatchData[0].docId);
let newCompletedMatchDocRef = db.collection("Match_Creator").doc("cricket").collection("completedMatchList").doc(getCompletedMatchData[0].docId);
return newCompletedMatchDocRef.set(getCompletedMatchData[0].docData); //set/copy the data to new path.
})
This is my main index.js file
const functions = require("firebase-functions");
const admin = require("firebase-admin");
const storeMatchData = require("./liveScoring");
const createCompletedMatchListDoc = require("./completedMatchList");
const { db } = require("./db/index");
var http = require("https");
module.exports = {
liveScoring: functions.https.onRequest(storeMatchData),
createCompletedMatchListDoc: functions.https.onRequest(
createCompletedMatchListDoc
)
};
Now after copy document data to a new path i will delete the previous document. For deleting the document i have not written the function.
I'm not seeing anything that would allow you to move a document between collections(someone correct me if I'm wrong). You have to copy from the old collection to the new one and then remove the old one.
This is another post on StackOverflow that is running into this same issue and someone provided Java code on how to implement it.
EDIT: Updated link.
Hope this helps.
I'm trying to scrape a website with load more button, but I can't do a recursive function with in nightmare. my code is something like this:
const Nightmare = require('nightmare');
const nightmare = Nightmare({
show:true
});// }
const request = require('request');
const cheerio = require('cheerio');
let url = 'https://www.housers.com/es/proyectos/avanzado';
let propertyArray = [];
var getThePage = function() {
nightmare
.goto('https://www.housers.com/es/proyectos/avanzado')
.wait(1500)
.click('#loadMore')
.evaluate(() =>{
return document.querySelector('.all-info').innerHTML;
})
.end()
.then((result) => {
let $ = cheerio.load(result);
let loadMore = $('#loadMore')
if (loadMore) {
getThePage();
}
return result
})
.catch((error) => {
console.error('Search failed:', error);
});
}
getThePage()
I don't know if you have any way to do it by this method or any other idea
If you want to scrap the data in the table, you don't need to use nightmare. From the network tab, you would see that it calls this endpoint :
https://www.housers.com/es/proyectos/avanzado/scroll
with some pagination & page size, let's take 200 per page (don't know if it's above the limit).
Then you just have to parse html & put data in an array :
const axios = require('axios');
const querystring = require('querystring');
const cheerio = require('cheerio');
const entities = require("entities");
const url = 'https://www.housers.com/es/proyectos/avanzado/scroll';
const prices = [];
function doRequest(url, page){
return axios.post(url + '?page=' + page + '&size=200', querystring.stringify({
word: "",
country: "",
type: "",
order: "STOCK_PRICE_VARIATION",
orderDirection: "DESC"
}));
}
async function getPrices() {
var empty = false;
var page = 0;
while (!empty) {
//call API
console.log("GET page n°" + page);
var res = await doRequest(url, page);
page++;
//parse HTML
const $ = cheerio.load(res.data,{
xmlMode: true,
normalizeWhitespace: true,
decodeEntities: true
});
if (res.data.trim() !== ""){
//extract prices : put it in array
$('tr').map(function(){
var obj = [];
$(this).children('td').map(function(){
obj.push(entities.decodeHTML($(this).text().trim()));
});
prices.push(obj);
});
}
else {
empty = true;
}
}
console.log(prices);
console.log("total length : " + prices.length);
}
getPrices();