I want to retrieve tweets and mentions from the twitter api. After doing this I want gather the tweets and mentions and store it in one json array. So far when I store both tweets and mentions, the system replaces the tweets in the object with the mentions?
jsonx = {};
var tweets = function(){
client.get('search/tweets', {q:"#"+string.teamname, count:1},
function (err,data){
for(var index in data.statuses){
var tweet = data.statuses[index];
jsonx[index] = tweet
}
})
}
var mentions = function(){
client.get('statuses/user_timeline', {screen_name:"#"+string.teamname, count:1},
function(err,data) {
for(var index in data){
var tweet = data[index];
jsonx[index] = tweet
}
})
}
var doSometing = function(tweets, mentions){
if (string.checktweet1 == 'on'){
tweets()
}
if (string.checkmentions1 == 'on'){
mentions()
}
}
doSometing(tweets,mentions)
Look into Object.assign() which is like merging to Objects (but in reality it creates a new Object). If you combine it with Array.concat, you can do something like this...
let jsonx = {
tweets: [],
mentions: []
};
// ....
let tweet = data.statuses[index];
jsonx = Object.assign({}, jsonx, {
tweets: jsonx.tweets.concat([tweet])
});
Your example involves mutation which is undesirable and leads to your mentions overriding tweets. This example is constantly creating a new object based on old data (same with Array.concat which creates a new array).
Related
Could someone tell me how to push elements into an array in localStorage?
My code:
(localStorage.getItem('projects') === null) ? localStorage.setItem('projects', ['proj1', 'proj2', 'proj3']) : '';
var ItemGet = localStorage.getItem('projects');
function CreateObject() {
console.log(ItemGet);
var Serializable = JSON.parse(ItemGet);
Serializable.push('proj4');
console.log(ItemGet);
}
<button onclick="CreateObject()">Add Object</button>
General approach:
let old_data = JSON.parse(localStorage.getItem('projects'))
let new_data = old_data.push(some_new_data)
localStorage.setItem('projects',JSON.stringify(new_data))
I would do the following assuming that your data is not a multiDimensional array.
(localStorage.getItem('projects') === null) ? localStorage.setItem('projects',
JSON.stringify(['proj1', 'proj2', 'proj3'])) : '';
var ItemGet = localStorage.getItem('projects');
function CreateObject() {
var Serializable = JSON.parse(ItemGet);
Serializable.push('proj4');
localStorage.setItem('projects',JSON.stringify(Serializable));
}
The problem you are hitting is that data stored in localStorage has to be a string. You'll have to parse/stringify before settting/getting anything from local storage. If you didn't want to work with strings, you may find something like IndexedDB API
const stuff = [ 1, 2, 3 ];
// Stringify it before setting it
localStorage.setItem('stuff', JSON.stringify(stuff));
// Parse it after getting it
JSON.parse(localStorage.getItem('stuff'));
Here is an example of using IndexedDB API from the docs
const dbName = "the_name";
var request = indexedDB.open(dbName, 2);
request.onerror = function(event) {
// Handle errors.
};
request.onupgradeneeded = function(event) {
var db = event.target.result;
// Create an objectStore to hold information about our customers. We're
// going to use "ssn" as our key path because it's guaranteed to be
// unique - or at least that's what I was told during the kickoff meeting.
var objectStore = db.createObjectStore("customers", { keyPath: "ssn" });
// Create an index to search customers by name. We may have duplicates
// so we can't use a unique index.
objectStore.createIndex("name", "name", { unique: false });
// Create an index to search customers by email. We want to ensure that
// no two customers have the same email, so use a unique index.
objectStore.createIndex("email", "email", { unique: true });
// Use transaction oncomplete to make sure the objectStore creation is
// finished before adding data into it.
objectStore.transaction.oncomplete = function(event) {
// Store values in the newly created objectStore.
var customerObjectStore = db.transaction("customers", "readwrite").objectStore("customers");
customerData.forEach(function(customer) {
customerObjectStore.add(customer);
});
};
};
There are also other solutions out there like PouchDB depending on your needs
Say for example you have an array. This is how you can store it in the local storage.
let my_array = [1, 2, 3, 4];
localStorage.setItem('local_val', JSON.stringify(my_array))
Now to push any data into the local storage array you have to override by the new data like bellow
let oldArray = JSON.parse(localStorage.getItem('local_val'))
oldArray.push(1000)
localStorage.setItem('local_val', JSON.stringify(oldArray))
Context: I'm fetching 'car' data below (see the code that starts with "for") from a GET request and am pushing it to the 'array' array. And for each car.ID that I get, I need to run another GET request in sequence (the GET uses car.ID as a parameter and I have no problems in doing this).
Problem: after I fetch the results from the second GET, how to push the data to the same object of the array (i.e. I want to "complement" the object above that ended on car.BrandID by adding a few more key: value pairs to the same "line")?
THANK YOU IN ADVANCE.
for (let car of carsJustObtained) {
for (i=0; i<=2; i++){
array.push(
{
timestamp: epoch,
ID : car.ID,
BrandID : car.BrandID
})
//code continues but don't worry
FULL CODE BELOW:
function gotCars(carsJustObtained) {
for (let car of carsJustObtained) {
for (i=0; i<=2; i++){
array.push(
{
timestamp: epoch,
ID : car.ID,
BrandID : car.BrandID,
ModelID : car.ModelID,
}
);
//given car.ID the second GET will be triggered because the path depends on this variable!
let path_get_all_prices = `xxx=${car.ID}?securityToken=xxx&vehiclePriceTypeID=xxx`;
let get = https.get(
{
hostname: 'xxx.com',
path: path_get_all_prices
},
(getRes) => {
console.log(`getting prices for car ${car.ID}...`);
var reply = "";
getRes.on("data", (chunk) => (reply += chunk));
const obj = JSON.parse(reply);
gotPrices(obj.Response);
}
);
function gotPrices(pricesJustObtained) {
for (let price of pricesJustObtained){
array.push(
//how to add results to the same array of the 1st GET? There are three 'prices' for each car.ID
)};
};
};
You have to find the index of your object in your array, then you can add everything you can to this object :
array[index].name = 'Hello';
There are many ways to do this. I recommend you read about array.map()
This function lets you iterate your array and in each iteration perform the get request and extend the current element.
The key is to recognise that you are not pushing, the second time
What you are doing is reading each element of the array, and adding some information to that element.
for (let car of carsJustObtained) {
const newInfo=getFurtherInformationAboutCar(car) // this is your second getting
car.newInfo1 = newInfo.param1;
car.newInfo2 = newInfo.param2;
car.newInfo3 = newInfo.param3;
}
To answer your specific question about "merging" information
If you have one set of properties already defined for the car, and you want to merge in multiple new properties, a simple way to do it is as follows:
car = { ...car, ...objectContainingNewProperties};
If your original car was {a:2, b:3, c:4} and objectContainingNewProperties was {c: 10, d:20, e:30}, the result would be:
{ a:2,
b:3,
c:10,
d:20,
e:30 }
Any same-named properties in the second object will overwrite those in the original object.
Your second request is of course asynchronous, so by the time you get its response, you have already populated your array with all information from the first request.
I would suggest to use a promise-enabled alternative to http.get, as promises are a native feature in JavaScript that makes working with asynchronous events less messy. I will show here how it can work with node-fetch.
As fetch is natively supported in browser agents, you can run the snippet below to see the result. As a demo I have used https://jsonplaceholder.typicode.com/ as a server resource: it returns JSON for several sample datasets, including todos and users. A todo has some properties (like a title) and has a user id. A user has an email and a username. So we could make the todos-request the first request, and the users-request the second one (based on the user id received in the first). So the principle is the same as with your cars and prices.
This relies heavily on promises:
// For demo, we use these two URls:
// They both need a number following it
let url1 = "https://jsonplaceholder.typicode.com/todos/";
let url2 = "https://jsonplaceholder.typicode.com/users/";
let promises = [];
// Let's say we build an array with 5 objects:
for (let i = 1; i <= 5; i++) {
promises.push(
// Make the request
fetch(url1 + i*30)
// Parse the response as JSON
.then(resp => resp.json())
// Process this data
.then(data => {
// Create our own object from this data
let obj = {
user: data.userId,
todo: data.title
};
// Make second request, to get user's email, joining it with obj
return Promise.all([obj, fetch(url2 + obj.user)])
})
.then(([obj, resp2]) => Promise.all([obj, resp2.json()]))
// Merge the new data with the old
.then(([obj, data2]) => Object.assign(obj, {
email: data2.email,
logon: data2.username
}))
);
}
// Wait for all requests to finish...
Promise.all(promises).then(results => {
console.log(results); // The result!
});
With async/await
The above can be made even more readable, if you use the async/await syntax:
let url1 = "https://jsonplaceholder.typicode.com/todos/";
let url2 = "https://jsonplaceholder.typicode.com/users/";
async function getOne(i) {
let resp = await fetch(url1 + i*30);
let data = await resp.json();
// Create object from first request
let obj = {
user: data.userId,
todo: data.title
};
// Make second request, joining it with obj
let resp2 = await fetch(url2 + obj.user);
let data2 = await resp2.json();
return Object.assign(obj, {
email: data2.email,
logon: data2.username
});
}
let promises = [];
for (let i = 1; i <= 5; i++) {
promises.push(getOne(i));
}
Promise.all(promises).then(results => {
console.log(results);
});
My Firebase data base contains JSON objects, each with the same parameters as seen below. Firebase data
I want to get an array that has each objects country. So if I have 4,000 objects I want to get an array of 4,000 strings all containing a country.
Right now I can get the console to log all the 4,000 objects into an array using the code below.
componentWillMount() {
this.fetchData();
}
fetchData = async () => {
var data1 = [];
var fireBaseResponse = firebase.database().ref();
fireBaseResponse.once('value').then(snapshot => {
snapshot.forEach(item => {
var temp = item.val();
data1.push(temp);
return false;
});
console.log(data1);
});
}
But when I try doing
var fireBaseResponse = firebase.database().ref().child('country');
I get an array of nothing.
Any help would be great.
As mentioned in the comments, you can create a new temp object containing just country before pushing it into your array.
snapshot.forEach(item => {
var temp = { country: item.val().country };
data1.push(temp);
return false;
});
Question: How do I store a large array full of objects, all of which have 5 properties and all except the id property must be updated. Further more, why won't the code below work and how can I format it to work with the main question?
Info I've viewed:
https://developer.mozilla.org/en-US/docs/Web/API/IDBObjectStore/openCursor
https://developer.mozilla.org/en-US/docs/Web/API/IndexedDB_API/Using_IndexedDB
https://developer.mozilla.org/en-US/docs/Web/API/IDBObjectStore/createIndex
Note: I am aware of the setInterval and its inefficiency, it is for testing purposes so I do not have to click many times to check for a result.
<html>
<body>
<script type="text/javascript">
let count =0;
let storeBuilt = false;
const dbName = "the_name";
let version=82;
let storeName= "store82";
let storeBuilding= false;
setInterval(build,1000/24);
function build(){
hello()
}
function hello(){
let customerData = [];
for(let i=0;i<=50000;i++){
customerData.push({name:"bob",minX:random(),minY:random(),maxX:random(),maxY:random(),id:random()})
}
let request = indexedDB.open(dbName, version);
request.onsuccess= function(event){
let db = event.target.result;
let transaction = db.transaction( storeName,"readwrite").objectStore(storeName);
if( storeBuilding=== false&& storeBuilt=== false){
storeBuilding= true;
let additem = addData(customerData, transaction);
additem.onsuccess= function(e){storeBuilt=true}
} else if (storeBuilt=== true){
let updateitem= updateData(customerData, transaction);
}
};
request.onupgradeneeded = function(event) {
let db = event.target.result;
// Create an objectStore to hold information about our customers. We're
// going to use "ssn" as our key path because it's guaranteed to be
// unique - or at least that's what I was told during the kickoff meeting.
let objectStore = db.createObjectStore(storeName, {keyPath:"names",autoIncrement:true});
objectStore.createIndex("name","name",{unique:true});
// Use transaction oncomplete to make sure the objectStore creation is
// finished before adding data into it.
objectStore.transaction.oncomplete = function(event) {
// Store values in the newly created objectStore.
let customerObjectStore = db.transaction(storeName, "readwrite").objectStore(storeName);
}
};}
function random (){
return (Math.floor((Math.random() * 10) + 1))
}
function addData(data,transaction){
return transaction.add(data)
}
function updateData(data,transaction){
let openCursor = transaction.index("name").openCursor();
openCursor.onsuccess= function(event){
let cursor = event.target.result;
if (cursor){
alert (cursor);
for(let I in data){
let item = data[I];
if(item.id === cursor.value.id){
let updateProperty = cursor.value;
updateProperty.minX = item.minX;
cursor.update(updateProperty);
cursor.continue()
}
}
}{alert("none")}
}
}
function deleteData(data,transaction){
}
</script>
</body>
</html>
Not sure if I understand the problem clearly, but generally you will want to load the objects from the object store, modify each object's properties, and then store the objects in the object store. There are several ways to do this. One way is to use cursor.update, but I don't think you need to do this at all. Just overwrite the objects.
function storeThings(db, things, callback) {
var txn = db.transaction('store82', 'readwrite');
txn.oncomplete = callback;
var store = txn.objectStore('store82');
for(var thing of things) {
store.put(thing);
}
}
function open(callback) {
var request = indexedDB.open();
request.onsuccess = _ => callback(request.result);
}
var things = [{id:1}, {id:2}, {id:3}];
open(db => storeThings(db, things, _ => console.log('done')));
I am using IDBObjectStore.prototype.put to store the objects. The put method will either create or overwrite an object in the store. It will create a new object in the store when no matching object is found based on the keypath. It will replace an existing object in the store when a matching object is found.
In your case, you are using ssn string as a keypath. So, in other words, it will create new people if ssn not found, or overwrite people if ssn found. You just need to make sure that the ssn property is defined within each person object you pass to put, or indexedDB will complain.
I've read several posts on the subject, but unfortunately struggling with my situation.
I am pulling some urls from an array of urls and then using those links to obtain (let's say) the title of the page from those subsites. At the end I want a list of original urls and an array of titles (from the sublinks). i.e., go into a site/domain, find some links, curl those links to find page titles.
Problem is that my titleArray just returns a Promise and not the actual data. I'm totally not getting closures right and promises. Code runs in node as is. I'm using personal sites in my real code, but substituted common sites to show an example.
const popsicle = require('popsicle');
var sites = ['http://www.google.com','http://www.cnn.com'];
// loop through my sites (here I'm just using google and cnn as a test
for(var i=0;i<sites.length;i++) {
// call function to pull subsites and get titles from them
var titleArray = processSites(sites[i]);
console.log(sites[i] + ": " + titleArray);
}
// get request on site and then get subsites
function processSites(url) {
return popsicle.get(url)
.then(function(res) {
var data = res.body;
// let's assume I get another collection of URLs
// that I pull from the main site
var subUrls = ['http://www.yahoo.com','http://www.espn.com'];
var titleArray = [];
for(var j=0;j<subUrls.length;i=j++) {
var title = processSubSites(subUrls[j])
titleArray.push(title);
}
return titleArray;
});
}
function processSubSites(url) {
return popsicle.get(url)
.then(function(res) {
var data = res.body;
// let's say I pull the title of the site somehow
var title = "The Title for " + url;
console.log(title);
return title;
});
}
The result after running this is:
http://www.google.com: [object Promise]
http://www.cnn.com: [object Promise]
The Title for http://www.espn.com
The Title for http://www.espn.com
The Title for http://www.yahoo.com
The Title for http://www.yahoo.com
whereas it should be:
http://www.google.com: ['The Title for http://www.yahoo.com', 'The Title for http://www.espn.com']
http://www.cnn.com: ['The Title for http://www.yahoo.com', 'The Title for http://www.espn.com']
...
You cannot return normal data from inside a Promise. You need to return another Promise to make it chainable. To process multiple Promise objects in loop, you need to push them in an array and call Promise.all(array);
const popsicle = require('popsicle');
var sites = ['http://www.google.com','http://www.cnn.com'];
var titleArrayPromises = [];
// loop through my sites (here I'm just using google and cnn as a test
for(var i=0;i<sites.length;i++) {
titleArrayPromises.push(processSites(sites[i]));
}
var titleArray = [];
Promise.all(titleArrayPromises).then(function (titleArrays) {
for(var i=0; i<titleArrays.length; i++) {
titleArray.concat(titleArrays[i])
}
// You now have all the titles from your site list in the titleArray
})
function processSites(url) {
return popsicle.get(url)
.then(function(res) {
var data = res.body;
// let's assume I get another collection of URLs
// that I pull from the main site
var subUrls = ['http://www.yahoo.com','http://www.espn.com'];
var titlePromiseArray = [];
for(var j=0;j<subUrls.length;j++) {
titlePromiseArray.push(processSubSites(subUrls[j]));
}
return Promise.all(titlePromiseArray);
});
}
function processSubSites(url) {
return popsicle.get(url)
.then(function(res) {
var data = res.body;
// let's say I pull the title of the site somehow
var title = "The Title for " + url;
return Promise.resolve(title);
});
}