So we have large data in JSON format.
We want to save it to a class (table) in our Parse app.
I wrote a JS script which can read the file and go through the JSON data.
But when is do the saving it all gets messed up. Its loops in the first one for ever. I understand that there is something called promise bt I don't understand how to use it? Can anyone help. My code is given below.
function processJson(result) {
object = JSON.parse(result);
verbose.textContent = "Read " + object.results.length + " objects";
var count = object.results.length;
var countAc = 0;
logger("To save: " + count);
i = 0;
while (i < count) {
if (object.results[i].areaType == 'ac') {
save(i).then(function (object) {
i = i + 1;
logger("Success: " + object.id);
});
} else {
logger("ac not found");
i = i + 1;
}
}
}
function save(i) {
logger("ac found");
var constituency = new Constituency();
constituency.set("points", object.results[i].points);
constituency.set("areaType", object.results[i].areaType);
constituency.set("name", object.results[i].name);
constituency.set("state", object.results[i].state);
constituency.set("index", object.results[i].index);
constituency.set("pc", object.results[i].pc);
constituency.set("center", object.results[i].center);
constituency.set("oldObjectId", object.results[i].objectId);
return constituency.save();
/*constituency.save().then(function(obj) {
// the object was saved successfully.
i = i + 1;
logger("Success: " + obj.id);
}, function(error) {
// the save failed.
logger(error.message);
i = i + 1;
});*/
}
I would do something like that:
function processJson(result) {
var object = JSON.parse(result);
for (var i = 0; i < object.results.legnth; i++){
var parseObject = createParseObjectFromJSONObject(object.results[i]);
parseObject.save(null).then(function(object){
console.log("object saved: " + object.id);
},function(error){
console.log("error: " + error);
});
}
}
function createParseObjectFromJSONObject(jsonObject){
var constituency = new Constituency();
constituency.set("points", jsonObject.points);
constituency.set("areaType", jsonObject.areaType);
constituency.set("name", jsonObject.name);
constituency.set("state", jsonObject.state);
constituency.set("index", jsonObject.index);
constituency.set("pc", jsonObject.pc);
constituency.set("center", jsonObject.center);
constituency.set("oldObjectId", jsonObject.objectId);
return constituency;
}
You can do it even better..
You can first push all the parse objects into array and then call saveAll to save all the parse objects in one request. This solution is good for < 1000 records .. if you have more than 1000 then you can do paging (first 1000 and saveAll, other 1000 and saveAll ....)
In this version your code will look like this:
function processJson(result) {
var object = JSON.parse(result);
var allObjects = [];
for (var i = 0; i < object.results.legnth; i++){
var parseObject = createParseObjectFromJSONObject(object.results[i]);
allObjects.push(parseObject);
}
// outside the loop we are ready to save all the objects in
// allObjects array in one service call!
if (allObjects.length > 0){
Parse.Object.saveAll(allObjects).then(function(){
console.log("all objects were saved!");
// all object ids are now available under the allObjects array..
},function(error){
console.log("error: " + error);
});
}
}
function createParseObjectFromJSONObject(jsonObject){
var constituency = new Constituency();
constituency.set("points", jsonObject.points);
constituency.set("areaType", jsonObject.areaType);
constituency.set("name", jsonObject.name);
constituency.set("state", jsonObject.state);
constituency.set("index", jsonObject.index);
constituency.set("pc", jsonObject.pc);
constituency.set("center", jsonObject.center);
constituency.set("oldObjectId", jsonObject.objectId);
return constituency;
}
Good Luck :)
Related
I need to get a value from excel file when status column value is “Y” and I wanted to return the value from Name Column to the calling function and excel sheet contains the data is as follows
Name Number status
YYYY 1234 N
XXXXX 3456 Y
Function I have written like this
var Excel = require(‘exceljs’);
var workbook = new Excel.Workbook();
var selectStatus = ’’;
module.exports = function() {
return actor({
trimSelectName: function() {
workbook.xlsx.readFile("E:/testData.xlsx")
.then(function(sheetName) {
// use workbook
i = 1;
try {
var workSheet = workbook.getWorksheet("trim");
workSheet.eachRow({
includeEmpty: false
}, function(row, rowNumber) {
if (i == 1) {
i = 0;
} else {
currRow = workSheet.getRow(rowNumber);
console.log("Name :" + currRow.getCell(1).value + ", Number :" + currRow.getCell(2).value +
"Select Status :" + currRow.getCell(3).value);
selectStatus = currRow.getCell(3).value;
if (selectStatus == "Y") {
return selectStatus;
}
}
});
} catch (Error) {
console.log(Error);
}
});
},
});
};
But I am trying to the print value from the calling function, I am always getting it as undefined
Calling function:
const selected = trimDataSelection.trimSelectName();
Could you please let me know where could be the issue?
As I see your function returns actor object, I assume you are using steps_file generated by codeceptjs which is used to extend "I" object in order to add your custom functions. So if you want to invoke your custom function from scenario you should call it like this: const selected = I.trimSelectName()
Hi I'm currently working on a Twitter bot with the Twitter API and Node.JS. I want the bot to return all of my followers and some of their features in an javascript object. Something like :
{['id', 'screen_name', 'name', 'screen_name', 'followers_count',
'friends_count']}
RN my code is :
var Twitter = new TwitterPackage(config);
var options =
{
screen_name: 'mowsolicious',
};
Twitter.get('followers/ids', options, function (err, data) { // returns a list of ids
var nbFollowers = data.ids.length
var id = []
console.log(nbFollowers) // how many followers I have
for (i=0 ; i <= nbFollowers ; i++) {
ids = data.ids
var id = ids[i]
Twitter.get('users/show/' + id, function(err, data) {
console.log(id + " - " + data.name + " - " + data.screen_name + " - " + data.followers_count + " - " + data.friends_count)
})
}
})
I'm pretty sure something is terribly wrong with my method (more precisely when I put the Twitter.get thing in the loop) and it returns a bunch of undefined in the console.
I tried to work with the API doc but I'm experiencing some troubles understanding it. If someone could help that would be great.
Thank you
Most likely, you get undefined because the user is not found :
[ { code: 50, message: 'User not found.' } ]
Checking err variable would take care of that. But looking at GET followers/id documentation, you should use GET users/lookup to efficiently request mutliple user objects (up to 100 user per request with user id delimited by comma)
Also, I assume you'd like a unique callback to be called when all requests are completed, using Promises will take care of that :
var res_array = [];
function getUserInfo(id_list) {
return Twitter.get('users/lookup', {
"user_id": id_list
}).then(function(data) {
res_array.push(data);
})
.catch(function(error) {
throw error;
})
}
Twitter.get('followers/ids', function(err, data) {
if (err) {
console.log(err);
return;
}
console.log("total followers : " + data.ids.length);
var requestNum = Math.floor(data.ids.length / 100);
var remainder = data.ids.length % 100;
var promises_arr = [];
for (var i = 0; i < requestNum; i++) {
promises_arr.push(getUserInfo(data.ids.slice(i * 100, i * 100 + 100).join(",")));
}
if (remainder != 0) {
promises_arr.push(getUserInfo(data.ids.slice(requestNum * 100, requestNum * 100 + 100).join(",")));
}
Promise.all(promises_arr)
.then(function() {
for (var i in res_array) {
for (var j in res_array[i]) {
var user = res_array[i][j];
console.log(user.id + " - " +
user.name + " - " +
user.screen_name + " - " +
user.followers_count + " - " +
user.friends_count)
}
}
})
.catch(console.error);
})
List of followers can be retrieved with superface sdk , try it based on the example below
npm install #superfaceai/one-sdk
npx #superfaceai/cli install social-media/followers
const { SuperfaceClient } = require('#superfaceai/one-sdk');
const sdk = new SuperfaceClient();
async function run() {
// Load the installed profile
const profile = await sdk.getProfile('social-media/followers');
// Use the profile
const result = await profile
.getUseCase('GetFollowers')
.perform({
profileId: '429238130'
});
return result.unwrap();
}
run();
This works pretty fine
import fetch from 'node-fetch'
async function getFollowers(username) {
const response = await fetch(`https://api.twitter.com/1.1/followers/list.json?screen_name=${username}`, {
headers: {
Authorization: `Bearer ${<yourbearertoken>}`
}
});
// Parse the response as JSON
const data = await response.json();
return data.users;
}
const followers = await getFollowers("<username>");
I'm working on implementing a system where elements can be dragged and dropped to create flowcharts. My Issue is with saving the flowchart so that it could be reloaded when needed. For now I've created a method that saves all the previous data of the element onto the final array that holds only elements that are dropped on the container. But I'm getting a Trivial Error as Undefined variable on the debugging interface. Hence I'm not getting the intended output and the alert messages that I included are not being printed when the condition is met.
Code in Context
function saveFlowchart()
{
var nodes = [];
var matches = [];
var searchEles = document.getElementById("container").children;
for(var i = 0; i < searchEles.length; i++)
{
matches.push(searchEles[i]);
var idOfEl = searchEles[i].id;
if(searchEles[i].id !=null || searchEles[i].id !="")
{
var $element = $("#" + searchEles[i].id);
var dropElem = $("#" + searchEles[i].id).attr('class');
var position = $element.position();
position.bottom = position.top + $element.height();
position.right = position.left + $element.width();
alert("class:"+dropElem+"\nTop position: " + position.top + "\nLeft position: " + position.left + "\nBottom position: " + position.bottom + "\nRight position: " + position.right);
finalArray[idOfEl-1][0]= idOfEl;
finalArray[idOfEl-1][1]= dropElem;
var elId = parseInt(idOfEl);
if (dropElem == "stream ui-draggable")
{
for(var count=0;count<100;count++)
{
alert("One loop opened with count="+count);
if(createdImportStreamArray[count][0]==elId)
{
finalArray[elId-1][2]= createdImportStreamArray[count][1]; //Selected Stream from Predefined Streams
finalArray[elId-1][3]= createdImportStreamArray[count][2]; //asName
alert("createdImportStreamArray[count][0]==elId");
}
else if(createdExportStreamArray[count][0]==elId)
{
finalArray[elId-1][2]= createdExportStreamArray[count][1]; //Selected Stream from Predefined Streams
finalArray[elId-1][3]= createdExportStreamArray[count][2]; //asName
}
else if(createdDefinedStreamArray[count][0]==elId)
{
finalArray[elId-1][2]= createdDefinedStreamArray[count][1]; //Stream Name
finalArray[elId-1][3]= createdDefinedStreamArray[count][4]; //Number of Attributes
finalArray[elId-1][4]=[];
for(var f=0;f<createdDefinedStreamArray[r][4];f++)
{
finalArray[elId-1][4][f][0]=createdDefinedStreamArray[count][2][f][0]; //Attribute Name
finalArray[elId-1][4][f][1]=createdDefinedStreamArray[count][2][f][1]; // Attribute Type
}
}
alert("One loop closed with count="+count);
}
alert("Loop ended with count="+count);
}
else if (dropElem == "wstream ui-draggable")
{
ElementType="wstream";
}
// else if conditions...
alert(finalArray);
}
}
//Code to output the connection details in a json format
//The following is not affected by the above mentioned error
$(".node").each(function (idx, elem) {
var $elem = $(elem);
var endpoints = jsPlumb.getEndpoints($elem.attr('id'));
console.log('endpoints of '+$elem.attr('id'));
console.log(endpoints);
nodes.push({
blockId: $elem.attr('id'),
nodetype: $elem.attr('data-nodetype'),
positionX: parseInt($elem.css("left"), 10),
positionY: parseInt($elem.css("top"), 10)
});
});
var connections = [];
$.each(jsPlumb.getConnections(), function (idx, connection) {
connections.push({
connectionId: connection.id,
pageSourceId: connection.sourceId,
pageTargetId: connection.targetId
});
});
var flowChart = {};
flowChart.nodes = nodes;
flowChart.connections = connections;
flowChart.numberOfElements = numberOfElements;
var flowChartJson = JSON.stringify(flowChart);
//console.log(flowChartJson);
$('#jsonOutput').val(flowChartJson);
}
Debugging Interface
According to this the count variable in the for loop is undefined. I've tried taking the first statement var count=0 outside the loop declaration part and defining it in the very beginning of the method. But that simply checks for count=0 against the conditions and doesn't increment at all.
Any help in this regard will be highly appreciated as I've been working on this minor error for almost 2 days now.
I am reasonably new to node.js / sails.js and have run into a problem that I know the answer is simple but I cannot seem to work it out.
My code is as follows
SendCompleted : function(req,res)
{
var updated = 0;
var params = req.params.all();
var dt = JSON.parse(decodeURI(params.id));
var connection = new sql.Connection(testrmis, function (err)
{
if (err) {
}
for(var i = 0; i < dt.length; i++) {
var obj = dt[i];
var request = new sql.Request(connection);
request.stream = true;
request.input('branchid', sql.Int(), obj.branch_id);
request.input('picklistid', sql.Int(), obj.picklist_id);
request.input('scanned',sql.Int(),obj.scanned);
request.input('expected', sql.Int(),obj.expected);
request.input('poscode', sql.VarChar(),obj.poscode);
request.input('label', sql.VarChar(), obj.label);
request.input('dt', sql.VarChar(), obj.dt);
request.execute('WAREHOUSE_InsertPiPackData');
request.on('done', function(returnValue) {
updated = updated + returnValue;
console.log(updated);
});
}
res.send("[{\"ReturnValue\":" + updated + "}]");
});
}
I am sending in 4 lines of results and my console.log(updated) counts up as it should for each line, e.g 1,2,3,4
However the res.send result for updated is always 0.
Could anyone please explain why this is happening? My var updated is outside of my loop and this is getting updated correctly, however when the loop is finished it seems to get reset to 0?
returnValue == ##rowcount from the stored procedure
request is async so
res.send("[{\"ReturnValue\":" + updated + "}]");
gets executed even before you get the callback on request as JS doesn't wait for the callback and executes the next line. What you can do is use a counter and place your res.send inside for loop.
SendCompleted : function(req,res)
{
var updated = 0;
var params = req.params.all();
var dt = JSON.parse(decodeURI(params.id));
var connection = new sql.Connection(testrmis, function (err)
{
if (err) {
}
var count = dt.length;
for(var i = 0; i < dt.length; i++) {
var obj = dt[i];
var request = new sql.Request(connection);
request.stream = true;
request.input('branchid', sql.Int(), obj.branch_id);
request.input('picklistid', sql.Int(), obj.picklist_id);
request.input('scanned',sql.Int(),obj.scanned);
request.input('expected', sql.Int(),obj.expected);
request.input('poscode', sql.VarChar(),obj.poscode);
request.input('label', sql.VarChar(), obj.label);
request.input('dt', sql.VarChar(), obj.dt);
request.execute('WAREHOUSE_InsertPiPackData');
request.on('done', function(returnValue) {
count--;
updated = updated + returnValue;
console.log(updated);
if(count == 0) res.send("[{\"ReturnValue\":" + updated + "}]");
});
}
});
}
Try for this:
May be Async problem:
for(var i = 0; i < dt.length; i++) {
//Your logic
if(i=== dt.length){
res.send("[{\"ReturnValue\":" + updated + "}]");
}
}
This is because at the time you do request.send, the value of updated is not incremented. This is because request.execute is asynchronous and done handler will be invoked after the res.send has been executed.
I would recommend a promise library (example, q). You can combine the promises and then use Q.all to do req.send when all the promises are done.
See more details here
I write some simple app for windows 8 Metro UI with javascript. Because natural method from microsoft to use Sqlite with Javascript in Metro UI. I use 'doo' wrapper:
dooWrapper SQLite (github)
I create a method :
function addSomething(name) {
var dbPath = Windows.Storage.ApplicationData.current.localFolder.path + '\\a_db.sqlite';
SQLite3JS.openAsync(dbPath).then(function (db) {
return db.runAsync("INSERT INTO STH (nazwa) VALUES (:name)", { name: name }).
done(function () {
console.log('Add sth : ' + name);
db.close();
}, function (error) {
if (db) {
db.close();
}
console.log('ERROR Adding sth' + error.message);
})
});
}
I get error 'database is locked' I read about this error in documentation. But I have one question is other solution to add more rows without create 'insert' function with collections argument something like that : insert (array) ? I just want to use that function n-times without this error. That's possible?
Yes,it possible...i also got this error before....For that you just need to establish the database connection once...i have used this in my app and its working fine.
If there is no need of closing your db then then open database once like..
Add this code to default.js file
var myDatabase; //Global Variable
var dbPath = Windows.Storage.ApplicationData.current.localFolder.path + '\\db.sqlite';
//Create Table
SQLite3JS.openAsync(dbPath).then(function(db) {
myDatabase=db;
return db.runAsync('CREATE TABLE Item (name TEXT, price REAL, id INT PRIMARY KEY)');
});
Then you just need to use below code
// For Insert
return myDatabase.runAsync('INSERT INTO Item (name, price, id) VALUES ("'+ array[i].name+'", "48484", 1);
For array
var dbPromises = [];
var testArray = [];
//only for test purpose
//You can pass your array here directly
for (var a = 0; a < 300; a++) {
var obj = {
name: "Mango"+a,
price: 100+a,
id: a
};
testArray.push(obj);
}
for (var i = 0; i < testArray.length; i++) {
var query = 'INSERT OR REPLACE INTO Item (name, price, id) VALUES ("' + testArray[i].name + '",' + testArray[i].price + ',' + testArray[i].id + ')';
dbPromises.push(globalDatabase.allAsync(query));
}
WinJS.Promise.join(dbPromises).then(function () {
debugger;
}, function(err) {
debugger;
});
Above code is used only for less array size...bcz its taking too much time for insertion...
For fasst execution you should replace just below code
for (var i = 0; i < testArray.length; i++) {
var val = '("' + testArray[i].name + '",' + testArray[i].price + ',' + testArray[i].id + '),';
query = query + val;
if ((i + 1) % 300 == 0 || (i + 1) == testArray.length) {
query = query.replace(/,$/, "");
dbPromises.push(globalDatabase.allAsync(query));
query = 'INSERT OR REPLACE INTO Item (name, price, id) VALUES ';
}
}