How to call a variable which is declared inside firebase firestore - javascript

I have some values inside my Firebase > Firestore > Collection > Document.
i can acces them by,
db.collection("Fund").doc("Status").get().then((doc)=>{
let MTBNAV = doc.data().SPMTB
}
Now, I want to Access my MTBNAV outside the function without calling another function and setting an argument

Use the await to get MTBNAV. like this:
let MTBNAV = (await db.collection('Fund').doc('Status').get()).data().SPMTB
Try this.

much easier to understand code should be:
const myFunc = async () => {
const collectionRef = db.collection("Fund")
const doc = await collectionRef.doc("Status").get()
let MTBNAV = doc.data().SPMTB
}
}

Related

Call method on object also do async operation before

i'm using a library that return an object with multiple keys and methods to use, one of the key of this object is accessToken.
accessToken value must exist before calling any method of this object (otherwise you're not authenticated).
The token is retrieved externally using an async axios function, also this token is only valid for 1 hour, in this case it's okay to get a new token every time you call some function inside it.
I dont' want to recreate the object every time i use this library (i'm using this library multiple times).
So far based on few articles i found online i did this:
const force = require('jsforce')
const { SFAuth } = require('./auth')
const common = require('../common')
class JSForce {
constructor (connection) {
return connection
}
static async Connect () {
const token = await SFAuth.getToken()
const connection = new force.Connection({
instanceUrl: common.SALESFORCE_URL,
accessToken: token
})
return new JSForce(connection)
}
}
const start = async () => {
const res = await JSForce.Connect()
console.log(res)
}
start()
If i try to do JSForce.Connect().sobject('Account') i get an error saying sobject is not a function.
It works if first i save JSFORCE.Connect() in a new instance and then i use this instance.sobject() but i can't do it every time i need to use it.
How would you solve this?
Thanks!!
Problem is field sobject will only come once you have JSForce connection successful. First we need to make sure we have that and we can save in variable. We will only call JSForce if we don't have instance already.
Declare a global variable in file.
let instance: <any>
// This method will return instance always if we dont have
const getInstance = async () => {
if (!instance) {
instance = await JSForce.Connect();
}
return instance;
};
const start = async () => {
const res = await getInstance().sobject('Account');
console.log(res);
}
start();

How to take two fetches and compare their data as variables whilst not getting any errors?

I want to take two different fetches, put them into a variable form so their important data can be used for something else other than just logging the data.
I'm trying to do this via window response async, however, I am currently at a dead end because though what I'm doing works on one strand of data, it doesn't work on two because of the JSON body stream already read error.
let RESPONSE = window.Response.prototype.json;
window.Response.prototype.json = async function () {
if (!('https://a/')) return RESPONSE.call(this)
let x = await RESPONSE.call(this);
if (!('https://b/')) return RESPONSE.call(this)
let y = await RESPONSE.call(this);
for (let detect in x) {
if (x[detect] !== y[detect]) {
console.log(x[detect]);
console.log(y[detect]);
}
}
return x;
return y;
};
How can I keep the data in a variable form that can be used for something like this:
for (let detect in x) {
if (x[detect] !== y[detect]) {
console.log(x[detect]);
console.log(y[detect]);
}
but whilst being able to have both variables defined at the same time? This would mean I would need to get past the body stream error while also keeping that core code. How can I do that?
Does this help you?
async function doTwoRequestsAndCompareStatus() {
const res1 = await fetch("https://fakejsonapi.com/fake-api/employee/api/v1/employees");
const res2 = await fetch("https://fakejsonapi.com/fake-api/employee/api/v1/employees");
const data1 = await res1.json();
const data2 = await res2.json();
console.log('both were equal?', data1.status === data2.status);
}
// Don't forget the actually call the function 😉
doTwoRequestsAndCompareStatus();
Although I would recommend this, both because it's cleaner and faster, as the fetches are executed at the same time and not sequentially.
async function doTwoRequestsAndCompareStatus() {
const [data1, data2] = await Promise.all([
fetch("https://fakejsonapi.com/fake-api/employee/api/v1/employees").then(r => r.json()),
fetch("https://fakejsonapi.com/fake-api/employee/api/v1/employees").then(r => r.json()),
]);
console.log('both were equal?', data1.status === data2.status);
}
// Don't forget the actually call the function 😉
doTwoRequestsAndCompareStatus();
If you find the first one easier to understand though, I would recommend using it 👍.

Custom Function Not Defined Puppeteer

I made this custom function and put it outside globally which normally would work. I also tried moving it inside the main async puppeteer function but also doesn't work. Its a simple function. In each page evaluate function I call this and pass the selector. But, its saying not defined and promise rejection which is weird because the function isn't a promise....Please help
const grabDomConvertNodlistToArray = (grabDomHtmlPath) => {
// grabbing node list from html selector all
const nList = document.querySelectorAll(grabDomHtmlPath);
// converting nodelist to array to be returned
const array = Array.from(nList);
return array;
};
I tried turning the function into an async function adding a new parameter page. I then added async to my evaluate function and then passes the puppeteer page as an argument and still errors and not working.
const grabDomConvertNodlistToArray = async (page, grabDomHtmlPath) => {
try {
// grabbing node list from html selector all
const nList = await page.document.querySelectorAll(grabDomHtmlPath);
// converting nodelist to array to be returned
const array = Array.from(nList);
return array;
} catch (error) {
console.log(error);
}
};
So I have your typical puppeteer setup where you awai browser.newPage() then you goto(url). Then i added this;
await page.exposeFunction("grabDomConvertNodlistToArray", grabDomConvertNodlistToArray);
added async to my evaluate callback function aka async() => {}. But still when calling my custom function inside the above evaluate function it doesn't work for some reason.
Found A Solution But, It Doesn't Work For Me. I'm Getting array.forEach is not a method which indicates to me that inside my grabDomConvertNodlistToArray function its not grabbing the nodeList or converting it into an array. If it did then forEach would be a function.
Solution 3
const browser = await puppeteer.launch();
const page = await browser.newPage();
await page.goto(someURL);
var functionToInject = function(){
return 1+1;
}
var otherFunctionToInject = function(input){
return 6
}
await page.exposeFunction("functionToInject", functionToInject)
await page.exposeFunction("otherFunctionToInject", otherFunctionToInject)
var data = await page.evaluate(async function(){
console.log('woo I run inside a browser')
return await functionToInject() + await otherFunctionToInject();
});
return data
So erase the two functions above and convert it to use my function below.
const grabDomConvertNodlistToArray = (grabDomHtmlPath) => {
// grabbing node list from html selector all
const nList = document.querySelectorAll(grabDomHtmlPath);
// converting nodelist to array to be returned
const array = Array.from(nList);
return array;
};
Running my js file results in an error of array.forEach isn't a function which is weird because if the function worked as intended the const array inside my evaluate function would be an array because its = to the above function which is returning an array. So.....idk whats going on think it has something to do with the document.querySelectorAll() line.
const rlData = async () => {
const browser = await puppeteer.launch(
{
headless: true,
},
{
args: ["--flag-switches-begin", "--disable-features=OutOfBlinkCors", "--flag-switches-end"],
}
);
const pageBodies = await browser.newPage();
await pageBodies.goto("https://test.com/bodies", {
waitUntil: "load",
});
const grabDomConvertNodlistToArray = (grabDomHtmlPath) => {
// grabbing node list from html selector all
const nList = document.querySelectorAll(grabDomHtmlPath);
// converting nodelist to array to be returned
const array = Array.from(nList);
return array;
};
await pageBodies.exposeFunction("grabDomConvertNodlistToArray", grabDomConvertNodlistToArray);
const rlBodyNames = await pageBodies.evaluate(async () => {
// grabs all elements in html to make nodelist & converts it to an array
const array = grabDomConvertNodlistToArray(".testbodies > div > h1");
// push the data collected from array into data array and returned
const data = [];
array.forEach((element) => {
data.push(element.textContent);
});
return data;
});
}
rlData();
Guess I'm going to have to move the document.querySelectorAll functionality out of the custom function and back in the evaluate. However, the whole reason of making that custom function was to reduce the same code being used multiple times since my overall crawler is 238 lines long with a lot of repetitiveness. Not being able to call custom functions like mine is horrible for refactoring same code executions.
I gave up trying to get this to work and decided just to do it this way. Yeah it makes your code repetitive if you have more pages to scrape so you will be using the same code many times which is what I was trying to avoid but, puppeteer is the worse for refactoring your code maybe down the line the developers of said package will add the ability to easily use custom functions like how I was trying too.
const testNames = await pageBodies.evaluate(() => {
const nodeList = document.querySelectorAll(".test > div h2");
const array = Array.from(nodeList);
const data = [];
array.forEach((element) => {
data.push(element.textContent);
});
return data;
});
exposeFunction() is not suitable for your case: the exposed function is intended to tranfer data between browser and Node.js contexts so it can be wrapped under the hood in a code that serialize and deserialize arguments and returned data and some unserializable data (as DOM elements) can be lost. Try this instead:
const rlData = async () => {
const browser = await puppeteer.launch(
{
headless: true,
},
{
args: ["--flag-switches-begin", "--disable-features=OutOfBlinkCors", "--flag-switches-end"],
}
);
const pageBodies = await browser.newPage();
await pageBodies.evaluateOnNewDocument(() => {
window.grabDomConvertNodlistToArray = function grabDomConvertNodlistToArray(grabDomHtmlPath) {
// grabbing node list from html selector all
const nList = document.querySelectorAll(grabDomHtmlPath);
// converting nodelist to array to be returned
const array = Array.from(nList);
return array;
}
});
await pageBodies.goto("https://test.com/bodies", {
waitUntil: "load",
});
const rlBodyNames = await pageBodies.evaluate(() => {
// grabs all elements in html to make nodelist & converts it to an array
const array = grabDomConvertNodlistToArray(".testbodies > div > h1");
// push the data collected from array into data array and returned
const data = [];
array.forEach((element) => {
data.push(element.textContent);
});
return data;
});
}
rlData();

MongoDB Realm Functions: How to query the document count of a collection

I tried implementing using this:
const mongodb = context.services.get("mongodb-atlas");
const itemsCollection = mongodb.db("natcocuDB").collection("members");
And I tried to put it inside an object
let memberToInsert = arg;
memberToInsert.memberID = itemsCollection.count({}) + 1;
Then the result is this:
memberID : [object Promise]1"
So the count function is a Promise. I tried to "await" the count but the function editor of realm produces an error.
The error says it's missing some ";".
So I tried so separate it by creating an async function for the count.
async function getDocumentCount(collection) {
return await collection.count({}) + 1;
}
But the result is the same only an object:
memberID : Object
Do you have any idea how can I get the document count? Thanks!
Solved it already. I just made my parent function async. And the 'await' worked. Thanks.
use await
Db query is an async operation that returns a promise. So in order to get a response from it use await or a callback.
let memberToInsert = arg;
const count = await itemsCollection.count({});
memberToInsert.memberID = count + 1;
https://docs.mongodb.com/realm/functions/#behavior

Do you know how I can use async await withing a map function to change a variable in every loop?

Do you know how I can make sure that the value of "intentid" change for every loop within the map function? The wanted result is that intentid changes its value for every loop, so that a new value is sent to "someOtherAsyncApiFunction(someinnerfunction())". I need to use async/await, because "intentid2" calls an API.
let someobject = {1: {name: "Question"}, 2: {name: "Tipp"}, 3:{name: "Question"}}
intentid = "";
const someFunction = () => {
Object.keys(someobject).map(async (key,index) =>{
if (someobject[key].name === "Question") {
const someinnerfunction = () => {
let followupintent = intentid;
return followupintent
}
let intentid2 = await someOtherAsyncApiFunction(someinnerfunction())
intentid = intentid2
console.log(intentid)
}}
)
}
someFunction()
When you use an asnyc mapper function you will get an array of promises.
In order to resolve them, you could use Promise.all()
const result = await Promise.all(values.map(async x => doSomething(x)))

Categories

Resources