Cannot read a public array item inside chained AXIO transactions in VUE - javascript

I have a chained AXIOS call that is being called from an array. I need to have the second call finish before the first one makes another API request and the process works fine. My only problem is that I can't reference anything from inside the response of the second chain. I need to update either the calling array(arr) a public array this.excelData.results or even a deep copy of the original array. Every time I get an error saying:
err = TypeError: Cannot read property 'ORCID' of undefined at eval (webpack-
internal:///./node_modules/cache-loader/dist/cjs.js?!./node_modules/babel-
loader/lib/index.js!./node_modules/cache-loader/dist/cjs.js?!./node_modules/vue-
loader/lib/index.js?!./src/views/examples/ExcelWorksheet.vue?vue&type=script&lang=js&:410:49) at
NodeList.forEach (<anonymous>) at eval (webpack-internal:///./node_modules/cache-
loader/dist/cjs.js?!./node_modules/babel-loader/lib/index.js!./node_modules/cache-
loader/dist/cjs.js?!./node_modules/vue-loader/lib/index.js?!./src/views/examples/ExcelWorksheet.vue?
vue&type=script&lang=js&:381:28) at NodeList.forEach (<anonymous>) at eval (webpack-
internal:///./node_modules/cache-loader/dist/cjs.js?!./node_modules/babel-
loader/lib/index.js!./node_modules/cache-loader/dist/cjs.js?!./node_modules/vue-
loader/lib/index.js?!./src/views/examples/ExcelWorksheet.vue?vue&type=script&lang=js&:378:33)
I have tried adding this or self but nothing seems to help. As I debug in a browser I can see all of the elements of the array but I can't read them in code or change them. Is there something special that I need to do so that I can use the data from the second AXIOS call in the original array?
lookUpORCID(){
this.pubmedArticles=[];
this.makeRequestsFromArray(this.excelData.results);
},
makeRequestsFromArray(arr) {
var self = this
let index = 0;
function request() {
let authorName = arr[index]["Last_Name"]
let linkGetIdList = 'https://eutils.ncbi.nlm.nih.gov/entrez/eutils/esearch.fcgi?';
linkGetIdList += 'tool=biosketch&db=pubmed&retmode=json&retmax=200&';
linkGetIdList += 'term=' + authorName +'[AU] ';
return axios.get(linkGetIdList).then((res) => {
index++;
let idlist = res.data.esearchresult.idlist
const passID = idlist.join(',')
if (idlist.length > 0) {
var getXmlLink = 'https://eutils.ncbi.nlm.nih.gov/entrez/eutils/efetch.fcgi?';
getXmlLink += 'db=pubmed&retmode=xml&id=${passID}';
return axios.get(getXmlLink).then((response) => {
// parse document
const parser = new DOMParser()
const xmlDoc = parser.parseFromString(response.data, 'text/xml') // Get ALL XML content
// Do Stuff
**This is the spot that I need to change value in array**
let xyz = arr[index]["ORCID"]
return request();
})
}
if (index >= arr.length) {
return 'done'
}
});
}
return request();
},

You are able to access the arr or the error would have been: cannot read property index of undefined.
You have incremented index after the first request & the arr has the value undefined at the incremented index, so the error says Cannot read property 'ORCID' of undefined.
You can try console.log(arr[index]) before let xyz = arr[index]["ORCID"] to verify above.

Related

Map number counting

let adminMap = new Map()
async function orionCheck(interaction, adminMap) {
const guild = await client.guilds.fetch(General.SERVER.ID)
const members = await guild.members.fetch()
var memberList = [];
members.forEach(member => memberList.push(member.user.id));
for (let i = 0; i < memberList.length; i++) {
if (members.get(memberList[i]).roles.highest.permissions.has("ADMINISTRATOR")) adminMap.set(members.get(memberList[i]).user.id, {BPM: 0, KPM: 0}) //console.log(members.get(memberList[i]).user.id)
}
var orionObjects = {
banObject: ["API/Orion Objects/OrionData.json", "Ban", "BPM", adminMap.get(interaction.user.id).BPM],
kickObject: ["API/Orion Objects/Kickbject.syrex", "Kick", "KPM", adminMap.get(interaction.user.id).KPM]
}
var objectPick = orionObjects.unknown;
if (interaction.commandName == 'ping' && General.SERVER.CHANNELS.LOGS !== "") {
objectPick = orionObjects.banObject;
if (client.orion == undefined) {
client.orion = adminMap;
console.log(client.orion.get(interaction.user.id), "client.orion made")
} else {
client.orion.set(client.orion.get(interaction.user.id).BPM, client.orion.get(interaction.user.id).BPM++)
console.log(client.orion.get(interaction.user.id))
//console.log(client.orion)
}
} else return; //ping and topic cmds are used as placeholder for ban and kick
if (interaction.commandName == 'topic' && General.SERVER.CHANNELS.LOGS !== "") {
} else return;
}
client.on('interactionCreate', async interaction => {
if (!interaction.isCommand()) return;
orionCheck(interaction, adminMap);
});
this is code for every time a command is executed, it adds 1 to your specific user on a map which is what the map is there for. the client.orion is set to the map so that it remembers it each time the command is executed and makes the map globally executable. the if statement is checking if the client.orion was already made and if its undefined it makes it. pretty simple. but the problem is, for some reason on startup, you execute the command. it makes the client.orion then you execute it again and it does the else statement since now client.orion already exists and it adds one to the array. but when you execute it a third time, it stays at one as shown
https://i.imgur.com/Uve78bx.png
This isn't a solution to your particular problem (but maybe it can provide some clues on what I was referring to in comments.)
On a Map object, set takes two parameters, the key and the value.
You have this line in your else block:
client.orion.set((interaction.user.id).BPM, client.orion.get(interaction.user.id).BPM++)
Notice that the "key" is undefined because (interaction.user.id).BPM doesn't exist.
You should have this line instead:
client.orion.set(interaction.user.id, client.orion.get(interaction.user.id).BPM++)
I thought it was strange when tested your code both ways (as undefined, and as defined) and got the same results. But whats really going on is that the set() is doing no work when the key passed to it is undefined. Instead the code in the value parameter is doing work (even though set() is not):
client.orion.get(interaction.user.id).BPM++
ALSO:
Your value parameter to set() has a logical error in that it's supposed to be an object. You are passing a integer to it. You didn't encounter what unexpected results this will create because so far your set() isn't doing work due to the undefined key.

How to access field on an array in cloud function?

I have this cloud function that creates a new document every time I have a new chat. I am trying to access the values on the messages array, but I got undefined on the console log.
here is my document on firebase:
I am trying to access the messages with lastMessage = data.messages to create a new document with these values on my function:
exports.onConversationCreated = functions.firestore.document('chat/{chatId}')
.onCreate((snapshot, context) => {
let data = snapshot.data();
let chatId = context.params.chatId;
if(data){
let members = data.members;
let lastMessage = data.messages;
for(let index = 0; index < members.length; index++){
let currentUserId = members[index];
let remainingUsersId = members.filter((u) => u != currentUserId);
console.log(lastMessage.message);
remainingUsersId.forEach((m) => {
return admin.firestore().collection('authUsers').doc(m).get().then( (_doc) => {
let userData = _doc.data();
if(userData) {
return admin.firestore().collection("authUsers")
.doc(currentUserId).collection('chat').doc(m).create({
"chatId": chatId,
"image": userData.photoUrl,
"name": userData.displayName,
"unseenCount": 0,
"lastMessage": lastMessage.message,
"timestamp": lastMessage.timestamp,
"type": lastMessage.type
});
}
return null;
}).catch(() => {return null});
})
}
}
return null;
});
I am trying to access the value message which is in the messages array, but I get undefined on the console log, do you guys know how I can access it?
This is because the messages field is an Array with one element, exactly like the members field is an Array with two elements. We can see that from the screenshot of your Firestore database: members has two elements (of type String), indexed with 0 and 1, and messages has one element (of type Map), indexed with 0.
You therefore need to access it as follows:
let lastMessage = data.messages;
//....
console.log(lastMessage[0].message);
It is not clear, from the content of your question, if there is any specific reason for defining the messages field as an Array. Are there any cases when you have several elements? If no, you should probably directly save the messages data as a Map.
In addition, note that you are incorrectly managing the life cycle of your Cloud Function. You should return a Promise when all the asynchronous work is completed. See the doc for more details.
Since you are executing a variable number of calls to Firebase asynchronous methods in a forEach loop, you should use Promise.all().

Any way to ensure I get the return value from a sequence of async functions

I'm working with repos and trying to get the pull requests, issues and commits for a repo. I have the following code:
const axios = require('axios');
var gitPullApiLink = "https://api.github.com/repos/alirezadir/Production-Level-Deep-Learning/pulls"
var listOfCommits = [];
var listOfSHAs = [];
var mapOfInfoObjects = new Map();
var mapPullRequestNumberToCommits = new Map();
var mapPRNumbersToCommitObjects = new Map();
var listOfPrObjects = [];
var setOfFileObjects = new Set();
var listOfNumbersOfTargetedIssues = [];
var mapPRnumberToCloseOpenDateObjects = new Map();
class PullRequestParser {
async getListOfPullRequests(pullrequestLink) {
const message = await axios.get(pullrequestLink);
//console.log(message);
listOfPrObjects = message['data'];
}
async getCommitsForEachPullRequestAndPRinformation() {
var listOfPrNumbers = [];
var k;
// this loop will just make a list of Pull Request Numbers
for (k = 0; k < listOfPrObjects.length; k++){
var currPrNumber = listOfPrObjects[k]['number'];
listOfPrNumbers.push(currPrNumber);
}
// I created a separate list just because... I did it this way because on the github API website it seems
// like the pull request has the same number as the issue it affects. I explain how you can see this down below
listOfNumbersOfTargetedIssues = listOfPrNumbers;
// next loop will make objects that contain information about each pull request.
var n;
for (n = 0; n < listOfPrNumbers; n++){
var ApiLinkForEachPullRequest = gitPullApiLink + "/" + listOfPrNumbers[n];
const mes = await axios.get(ApiLinkForEachPullRequest);
var temp = {OpeningDate: mes['data']['created_at'],
ClosingDate: mes['data']['closed_at'],
IssueLink: mes['data']['_links']['issue']['href']};
//mapPRnumberToCloseOpenDateObjects will be a map where the key is the pull request number and the value
// is the object that stores the open date, close date, and issue link for that pull request. The reason
// why I said I think the pull request number is the same as the number of the issue it affects is because
// if you take any object from the map, say you do mapPRnumberToCloseOpenDateObjects.get(10). You'll
// get an object with a pull request number 10. Now if you take this object and look at it's "IssueLink"
// field, the very last part of the link will have the number 10, and if you look at the github API
// it says for a single issue, you do: /repos/:owner/:repo/issues/:issue_number <---- As you can see,
// the IssueLink field will have this structure and in place of the issue_number, the field will be 10
// for our example object.
mapPRnumberToCloseOpenDateObjects.set(listOfPrNumbers[n], temp);
}
//up to this point, we have the pull request numbers. we will now start getting the commits associated with
//each pull request
var j;
for (j = 0; j < listOfPrNumbers.length; j++){
var currentApiLink = gitPullApiLink + "/" + listOfPrNumbers[j] + "/commits";
const res = await axios.get(currentApiLink);
//here we map a single pull request to the information containing the commits. I'll just warn you in
// advance: there's another object called mapPRNumbersToCommitObjects. THIS MAP IS DIFFERENT! I know it's
// subtle, but I hope the language can make the distinction: mapPullRequestNumberToCommits will just
// map a pull request number to some data about the commits it's linked to. In contrast,
// mapPRNumbersToCommitObjects will be the map that actually maps pull request numbers to objects
// containing information about the commits a pull request is associated with!
mapPullRequestNumberToCommits.set(listOfPrNumbers[j], res['data']);
}
// console.log("hewoihoiewa");
}
async createCommitObjects(){
var x;
// the initial loop using x will loop over all pull requests and get the associated commits
for (x = 0; x < listOfPrObjects.length; x++){
//here we will get the commits
var currCommitObjects = mapPullRequestNumberToCommits.get(listOfPrObjects[x]['number']);
//console.log('dhsiu');
// the loop using y will iterate over all commits that we get from a single pull request
var y;
for (y = 0; y < currCommitObjects.length; y++){
var currentSHA = currCommitObjects[y]['sha'];
listOfSHAs.push(currentSHA);
var currApiLink = "https://api.github.com/repos/alirezadir/Production-Level-Deep-Learning/commits/" + currentSHA;
const response = await axios.get(currApiLink);
//console.log("up to here");
// here we start extracting some information from a single commit
var currentAuthorName = response['data']['commit']['committer']['name'];
var currentDate = response['data']['commit']['committer']['date'];
var currentFiles = response['data']['files'];
// this loop will iterate over all changed files for a single commit. Remember, every commit has a list
// of changed files, so this loop will iterate over all those files, get the necessary information
// from those files.
var z;
// we create this temporary list of file objects because for every file, we want to make an object
// that will store the necessary information for that one file. after we store all the objects for
// each file, we will add this list of file objects as a field for our bigger commit object (see down below)
var tempListOfFileObjects = [];
for (z = 0; z < currentFiles.length; z++){
var fileInConsideration = currentFiles[z];
var nameOfFile = fileInConsideration['filename'];
var numberOfAdditions = fileInConsideration['additions'];
var numberOfDeletions = fileInConsideration['deletions'];
var totalNumberOfChangesToFile = fileInConsideration['changes'];
//console.log("with file");
var tempFileObject = {fileName: nameOfFile, totalAdditions: numberOfAdditions,
totalDeletions: numberOfDeletions, numberOfChanges: totalNumberOfChangesToFile};
// we add the same file objects to both a temporary, local list and a global set. Don't be tripped
// up by this; they're doing the same thing!
setOfFileObjects.add(tempFileObject);
tempListOfFileObjects.push(tempFileObject);
}
// here we make an object that stores information for a single commit. sha, authorName, date are single
// values, but files will be a list of file objects and these file objects will store further information
// for each file.
var tempObj = {sha: currentSHA, authorName: currentAuthorName, date: currentDate, files: tempListOfFileObjects};
var currPrNumber = listOfPrObjects[x]['number'];
console.log(currPrNumber);
// here we will make a single pull request number to an object that will contain all the information for
// every single commit associated with that pull request. So for every pull request, it will map to a list
// of objects where each object stores information about a commit associated with the pull request.
mapPRNumbersToCommitObjects.set(currPrNumber, tempObj);
}
}
return mapPRNumbersToCommitObjects;
}
startParsingPullRequests() {
this.getListOfPullRequests(gitPullApiLink + "?state=all").then(() => {
this.getCommitsForEachPullRequestAndPRinformation().then(() => {
this.createCommitObjects().then((response) => {
console.log("functions were successful");
return mapPRNumbersToCommitObjects;
}).catch((error) => {
console.log("printing first error");
console.log(error);
})
}).catch((error2) => {
console.log("printing the second error");
console.log(error2);
})
}).catch((error3) => {
console.log("printing the third error");
console.log(error3);
});
}
//adding some getter methods so they can be used to work with whatever information people may need.
//I start all of them with the this.startParsingPullRequests() method because by calling that method it gets all
// the information for the global variables.
async getSetOfFileObjects(){
var dummyMap = this.startParsingPullRequests();
return setOfFileObjects;
}
async OpenCloseDateObjects(){
var dummyMap = this.startParsingPullRequests();
return mapPRnumberToCloseOpenDateObjects;
}
async getNumbersOfTargetedIssues(){
var dummyMap = this.startParsingPullRequests();
return listOfNumbersOfTargetedIssues;
}
}
I'm trying to make a "dummy map" that gets the return value of calling startParsingPullRequests() in the following way:
var dummy = new PullRequestParser();
var dummyMap = dummy.startParsingPullRequests();
console.log(dummyMap);
But I end up with the following output:
undefined
3
1
functions were successful
I understand dummyMap is undefined because startParsingPullRequests() makes a series of async calls, but I'm wondering how do I go about making sure dummyMap gets its value and then prints. Thanks!
Since you already have code using async/await, why are you changing to .then? When you are using .then/.catch, it can be a lot harder to tell where things are waiting and what they are waiting on.
Here is your function converted to use async/await. With this change, you can await this function (though in that case, you might want to not catch the error and let the caller handle it, otherwise you need to check the return for undefined to "detect" the error). I've also simplified the error handling (but again, unless the code here can "fix" the problem, no reason to handle it here)
async startParsingPullRequests() {
try {
await this.getListOfPullRequests(gitPullApiLink + "?state=all");
await this.getCommitsForEachPullRequestAndPRinformation();
const response = await this.createCommitObjects();
console.log("functions were successful");
return mapPRNumbersToCommitObjects;
} catch (error) {
console.log("printing error");
console.log(error);
}
}

puppeteer evaluate functions not accepting JSHandles or ElementHandles as variables

I can pass native objects (strings, lists, numbers, etc) just fine, but whenever I try to pass in a JSHandle or ElementHandle, I get this error msg: "TypeError: Converting circular structure to JSON Are you passing a nested JSHandle? at JSON.stringify ()"
This is my code:
async getColumnsNames(id='dashboardGrid') {
await this.loadObjects();
const grid = this.table
const detectedColumns = await this.page.evaluate(({grid}) => {
//const grid = document.getElementById(id)
const header = grid.getElementsByClassName('ag-header-viewport')[0]
const labelRow = header.getElementsByClassName('ag-header-row')[0]
const cells = labelRow.getElementsByClassName('ag-header-cell-text')
var children = []
for(x = 0; x < cells.length; x++) {
cells[x].innerText.length > 0 ? children.push(cells[x].innerText) : null
}
return children
}, {grid});
console.log(detectedColumns)
}
So if I pass 'id' to obtain inside the 'grid' element, no problem (it's a CSS selector), but if I try to pass a handle (grid) directly, I get that error msg.
Said handle is exactly this:
this.table = await this.page.$(this.tableID);
Which totally works elsewhere for detecting the corresponding DOM element (this.tableID is '[id="dashboardGrid"]'), so I know the handle is NOT the problem.
The problem is that when you build your first argument like this {grid}, the resulting object is not an instance of JSHandle, so the evaluate won't treat that correctly.
This should work
const detectedColumns = await this.page.evaluate(grid => {
//Some code
}, grid);

How do I return specific values in an array in Javascript?

I'm trying to return specific values from an search that throws back a lot of information. The line which is causing me problems is this:
results = results.map((res) => res[0].tracks.items[10]);
I think it is the res[0] part as the error reads:
jquery.min.js:2 jQuery.Deferred exception: Cannot read property 'tracks' of undefined TypeError: Cannot read property 'tracks' of undefined
at results.map (http://127.0.0.1:60990/script.js:15:59)
at Array.map (native)
at Object.$.when.then.results (http://127.0.0.1:60990/script.js:15:35)
at j (https://ajax.googleapis.com/ajax/libs/jquery/3.1.1/jquery.min.js:2:29948)
at k (https://ajax.googleapis.com/ajax/libs/jquery/3.1.1/jquery.min.js:2:30262) undefined
I have used .tracks.items because the search throws back an array which is located within tracks and has a certain number of items - I want to return the first 10 items which is why I have placed the number 10 there.
Any ideas as to why it can't read res?
Bit more code context:
const app = {};
app.apiUrl = 'https://api.spotify.com/v1';
//Allow the user to enter names
app.events = function() {
$("form .submit-btn").click(function (e){
e.preventDefault();
let tracks = $('#itrack').val();
tracks = tracks.split(',');
let searcht = tracks.map(trackName => app.searchTrack(trackName));
$.when(...searcht)
.then((...results)=>{
results = results.map((res) => res[0].tracks.items[1]);
console.log(results);
});

Categories

Resources