I'm trying learnyounode(https://github.com/workshopper/learnyounode)
Exercise 9 ##JUGGLING ASYNC (try 3 get request and show response in the same order)
I wrote below code but result order is not stable. What's is wrong?
var http = require('http');
var bl = require('bl');
var urls = [];
for (var i = 2; i < process.argv.length; i++ ) {
urls.push(process.argv[i]);
};
var results = [];
for (var i = 0; i < urls.length; i++) {
http.get(urls[i], function(response) {
response.pipe(bl(function(err, data) {
if (err) {
console.error(err)
};
// if this code results[i] = data.toString() // console.log shows “”
results.splice(i, 0 , data.toString());
if ( results.length === urls.length) {
for (var i = 0; i < results.length ; i++) {
console.log(results[i]);
}
};
}));
});
}
official answer is below.
var http = require('http')
var bl = require('bl')
var results = []
var count = 0
function printResults () {
for (var i = 0; i < 3; i++) {
console.log(results[i])
}
}
function httpGet (index) {
http.get(process.argv[2 + index], function (response) {
response.pipe(bl(function (err, data) {
if (err) {
return console.error(err)
}
results[index] = data.toString()
count++
if (count === 3) {
printResults()
}
}))
})
}
for (var i = 0; i < 3; i++) {
httpGet(i)
}
Related
I have just started learning to develop an angularJS app,with my final objective being updating the angular version. As an initial step I wanted to remove $scope and refactor the following code into components. I have tried replacing $scope with 'this' but it somehow seems to break the code. Can anyone show me how to go about this?
Tool.showTool({ catalogId: catalogId, data: 'showTool' },
function (data) {
$scope.catalog = data;
$scope.tools = data.tools;
$scope.tools.filters = [];
$scope.tools.applicableFlagValues = [];
for (var index = 0; index < data.tools.length; index++) {
data.tools[index].category = angular.copy(data.tools[index].subCategory.tsCategory.category);
data.tools[index] = $scope.initItem($scope, data.tools[index], catalogId);
}
angular.forEach($scope.tools, function (detailedTool) {
GenericFilterService.addFilterItemsAsProperty(detailedTool, $scope.tools.filters);
ApplicableFlagService.addFlagValuesAsProperty(detailedTool, $scope.tools.applicableFlagValues);
});
if (nfrId !== undefined && nfrId !== '') {
Tool.calculateToolsProgressScoring({ tools: $scope.tools, nfrId: nfrId }, function (data, headers) {
var toolProgressList = data.result;
for (var index = 0; index < $scope.tools.length; index++) {
$scope.tools[index].progressCode = toolProgressList[index].progress;
$scope.tools[index].scoringVal = toolProgressList[index].scoring;
$scope.tools[index].criticalityAns = toolProgressList[index].criticality;
$scope.tools[index].compliancyAns = toolProgressList[index].compliancy;
$scope.tools[index].compliantAnsCount = toolProgressList[index].compliantAnsCount;
$scope.tools[index].totalAnsCount = toolProgressList[index].totalAnsCount;
}
});
}
if (tsId !== undefined && tsId !== '') {
Tool.calculateToolsProgressPerTs({ tools: $scope.tools, tsId: tsId }, function (data, headers) {
var toolProgressList = data.result;
for (var index = 0; index < $scope.tools.length; index++) {
$scope.tools[index].tsProgressCode = toolProgressList[index].progress;
$scope.tools[index].tsUsageAns = toolProgressList[index].usage;
$scope.tools[index].tsVersAns = toolProgressList[index].version;
$scope.tools[index].tsOtherVersAns = toolProgressList[index].otherversion;
$scope.tools[index].compliancyAns = toolProgressList[index].compliancy;
}
});
}
});
I am getting an error in console while i am trying to get a specific value from json data. This is the error:
'Uncaught TypeError: Cannot read property 'processen_id' of undefined'
Here is my code:
$.get("/getProces", function (data) {
if (data.error) {
} else {
for (var i = 0; i <= data.message.length; i++) {
var obj = data.message[i]
console.log(obj.processen_id)
}
}
})
}
This is what i get when i log (data):
You have a mistake in your code in the for loop
<= instead of <
$.get("/getProces", function (data) {
if (data.error) {
} else {
for (var i = 0; i < data.message.length; i++) {
var obj = data.message[i]
console.log(obj.processen_id)
}
}
})
}
The error message means that obj is undefined. That means, that data.message[i] gets an undefined value. The problem is the loop. You get an i that is larger then the array. Change <= to <:
for (var i = 0; i < data.message.length; i++) {
var obj = data.message[i]
console.log(obj.processen_id)
}
index out of range: for (var i = 0; i <= data.message.length; i++) { should be for (var i = 0; i < data.message.length; i++) { instead.
you can also optimize your code in this way:
$
.get("/getProces")
.then((res) => res.error ? Promise.reject(res) : Promise.resolve(res))
.then((data) => {
for (var i = 0; i < data.message.length; i++) {
var obj = data.message[i]
console.log(obj.processen_id)
}
})
Need help with the chaining. The functions work. But async calls make it hard for me to get everything. Help me think right!
My thought:
Get All Webs recursively (function works)
Get all lists from webs and iff announcementlist add to array and pass along
Get two items from all announcmentlists and sort by created.
Add ALL announcement items into one large array (to be able to sort array later.
Heres the code,
function getAllWebs(success, error) {
var ctx = SP.ClientContext.get_current();
var web = ctx.get_site().get_rootWeb();
var result = [];
var level = 0;
result.push(web);
var getAllWebsInner = function (web, result, success, error) {
level++;
var ctx = web.get_context();
var webs = web.get_webs();
ctx.load(webs, 'Include(Title,Webs,ServerRelativeUrl)');
ctx.executeQueryAsync(
function () {
for (var i = 0; i < webs.get_count() ; i++) {
var web = webs.getItemAtIndex(i);
result.push(web);
if (web.get_webs().get_count() > 0) {
getAllWebsInner(web, result, success, error);
}
}
level--;
if (level == 0 && success)
success(result);
},
error);
};
getAllWebsInner(web, result, success, error);
}
function error(sender, args) {
console.log(args.get_message());
};
function getAnnouncementLists(web, success, error) {
var dfd = $.Deferred();
var ctx = web.get_context();
var collList = web.get_lists();
var result = []
ctx.load(collList, 'Include(Title, Id, BaseTemplate)');
ctx.executeQueryAsync(function () {
for (var i = 0; i < collList.get_count() ; i++) {
var list = collList.getItemAtIndex(i);
var bTemp = list.get_baseTemplate();
if (bTemp == 104) {
result.push(list);
}
}
//success(result);
dfd.resolve(result);
}, error);
return dfd.promise();
}
function getListItems(list, success, error) {
var dfd = $.Deferred();
var camlQuery = new SP.CamlQuery();
camlQuery.set_viewXml('<View><Query><OrderBy><FieldRef Name="Created" Ascending="False"></FieldRef>'
+ '</OrderBy></Query><ViewFields><FieldRef Name="Title"/><FieldRef Name="Body"/>' +
'<FieldRef Name="Created"/></ViewFields><RowLimit>2</RowLimit></View>');
var listItems = list.getItems(camlQuery);
var result = []
var ctx = list.get_parentWeb().get_context();
ctx.load(listItems);
ctx.executeQueryAsync(function () {
for (var i = 0; i < listItems.get_count() ; i++) {
var item = listItems.getItemAtIndex(i);
result.push(item);
}
dfd.resolve(result);
//success(result);
}, error);
return dfd.promise();
}
function printResults(items) {
var sortedItems = items.sort(dynamicSort("get_created()"));
alert(sortedItems);
}
function dynamicSort(property) {
var sortOrder = 1;
if (property[0] === "-") {
sortOrder = -1;
property = property.substr(1);
}
return function (a, b) {
var result = (a[property] < b[property]) ? -1 : (a[property] > b[property]) ? 1 : 0;
return result * sortOrder;
}
}
$(document).ready(function () {
var items = getAllWebs(
function (allwebs) {
var array = [];
for (var i = 0; i < allwebs.length; i++) {
getAnnouncementLists(allwebs[i]).then(function (announceLists) {
for (var i = 0; i < announceLists.length; i++) {
getListItems(announceLists[i]).then(function (items) {
array.push(items);
});
}
});
}
return array;
}
);
//getAllWebs(
// function (allwebs) {
// for (var i = 0; i < allwebs.length; i++) {
// getAnnouncementLists(allwebs[i],
// function (announceLists) {
// for (var i = 0; i < announceLists.length; i++) {
// getListItems(announceLists[i],
// function (items) {
// printResults(items);
// }, error);
// }
// }, error);
// }
// }, error);
});
Given the requirements to retrieve list items from Announcements lists located across site collection, below is demonstrated the modified example that contains some improvements such as:
the number of requests to the server is reduced
fixed the issue in getAllWebs function that prevents to return any results if site contains only a root web
Example
function getAllWebs(propertiesToRetrieve,success, error) {
var ctx = SP.ClientContext.get_current();
var web = ctx.get_site().get_rootWeb();
var result = [];
var level = 0;
ctx.load(web, propertiesToRetrieve);
result.push(web);
var getAllWebsInner = function (web, result, success, error) {
level++;
var ctx = web.get_context();
var webs = web.get_webs();
var includeExpr = 'Include(Webs,' + propertiesToRetrieve.join(',') + ')';
ctx.load(webs, includeExpr);
ctx.executeQueryAsync(
function () {
for (var i = 0; i < webs.get_count() ; i++) {
var web = webs.getItemAtIndex(i);
result.push(web);
if (web.get_webs().get_count() > 0) {
getAllWebsInner(web, result, success, error);
}
}
level--;
if (level == 0 && success)
success(result);
},
error);
};
getAllWebsInner(web, result, success, error);
}
function loadListItems(lists,query,success,error,results){
var results = results || [];
var curList = lists[0];
var ctx = curList.get_context();
var listItems = curList.getItems(query);
ctx.load(listItems);
ctx.executeQueryAsync(function () {
results.push.apply(results, listItems.get_data());
lists.shift();
if(lists.length > 0) {
loadListItems(lists,query,success,error,results);
}
if(lists.length == 0)
success(results);
}, error);
}
function dynamicSort(property) {
var sortOrder = 1;
if (property[0] === "-") {
sortOrder = -1;
property = property.substr(1);
}
return function (a, b) {
var result = (a[property] < b[property]) ? -1 : (a[property] > b[property]) ? 1 : 0;
return result * sortOrder;
}
}
var propertiesToRetrieve = ['Lists.Include(BaseTemplate)','ServerRelativeUrl'];
getAllWebs(propertiesToRetrieve,
function(allwebs){
//1. get filtered lists
var allAnnouncementLists = [];
allwebs.forEach(function(w){
var announcementLists = w.get_lists().get_data().filter(function(l){
if(l.get_baseTemplate() == SP.ListTemplateType.announcements)
return l;
});
allAnnouncementLists.push.apply(allAnnouncementLists, announcementLists);
});
//2.Load list items from lists
var query = new SP.CamlQuery(); //<-set your custom query here
loadListItems(allAnnouncementLists,query,
function(allListItems){
//3.Sort and print results
var sortedItems = allListItems.sort(dynamicSort("get_created()"));
sortedItems.forEach(function(item){
console.log(item.get_item('Title'));
});
},logError);
},
logError);
function logError(sender,args){
console.log(args.get_message());
}
My Parse Javascript cloudcode is not working correctly. Basically all my objects have a corresponding "index/menindex & womenindex" number.
If both genders are selected- all items show up (as they should).
If just male or female is selected- it only shows items up to 122309 (womenindex) or 80811 (menindex). I've tried for weeks but cannot figure this one out.
Parse.Cloud.define("standardQuery", function(request, response) {
var maxIndex = 124940;
var maxWomenIndex = 135354;
var maxMenIndex = 105357;
var arrayOfRandomNumbers = new Array();
var query = new Parse.Query("garmentsAPI");
if (request.params.gender === "Female") {
//arrayOfRandoms draws on womenIndex, gender set to female
for (var k = 0; k < 40; k++) {
var randomIndex = Math.floor((Math.random()*maxWomenIndex)+1);
arrayOfRandomNumbers.push(randomIndex);
}
query.containedIn("womenIndex", arrayOfRandomNumbers);
query.notEqualTo ("viewers", request.params.user);
}else if (request.params.gender === "Male") {
for (var k = 0; k < 35; k++) {
var randomIndex = Math.floor((Math.random()*maxMenIndex)+1);
arrayOfRandomNumbers.push(randomIndex);
}
query.containedIn("menIndex", arrayOfRandomNumbers);
query.notEqualTo ("viewers", request.params.user);
//arrayOfRandoms draws on menIndex, gender set to male
}else{
for (var k = 0; k < 35; k++) {
var randomIndex = Math.floor((Math.random()*maxIndex)+1);
arrayOfRandomNumbers.push(randomIndex);
}
query.containedIn("index", arrayOfRandomNumbers);
query.notEqualTo ("viewers", request.params.user);
};
if (request.params.gender !== "both") {
query.equalTo ("gender", request.params.gender);
};
query.find({
success: function(objectsInQuery){
if (objectsInQuery.length > 15) {
var arrayOSelectedObjects = new Array();
for (var j = 0; j < 15; j++) {
arrayOSelectedObjects.push(objectsInQuery[j]);
}
response.success(arrayOSelectedObjects);
} else{
// var existingCount = objectsInQuery.count;
var missingIndex = 15 - objectsInQuery.length;
// missingIndex = missingIndex - objectsInQuery.count;
var query = new Parse.Query("garmentsAPI");
if (request.params.gender !== "both") {
query.equalTo ("gender", request.params.gender);
};
query.notEqualTo ("viewers", request.params.user);
query.limit(missingIndex);
// query.limit = 9 - objectsInQuery.count;
query.find({
success: function(objectsInQuery2){
if ((objectsInQuery.length + objectsInQuery2.length) === 15) {
for (var l = 0; l < missingIndex; l++) {
objectsInQuery.push(objectsInQuery2[l]);
}
response.success(objectsInQuery);
} else {
//who knows
var maxIndex2 = 15000;
var arrayOfRandomNumbers2 = new Array();
for (var m = 0; m < 15; m++) {
var randomIndex = Math.floor((Math.random()*maxIndex)+1);
// var randomIndex = 15;
arrayOfRandomNumbers2.push(randomIndex);
}
var query = new Parse.Query("garmentsAPI");
query.containedIn("index", arrayOfRandomNumbers2);
if (request.params.gender !== "both") {
query.equalTo ("gender", request.params.gender);
};
// query.notEqualTo ("viewers", request.params.user);
query.limit(15);
query.find ({
success: function (objectsInQuery3){
response.success (objectsInQuery3);
},
error:function() {
response.error("there was an error");
}
});
};
},
error:function() {
response.error ("didn't work");
}
}
);
};
},
error:function() {
response.error ("didn't work");
}
});
});
For starters, all the curly braces you've posted don't match up. Specifically, I can't find the closing brace for this if statement...
if (objectsInQuery.length > 15) {
It should be the first character of line 173, according to what you've posted...
as such...
});
};
},
error:function() {
response.error ("didn't work");
}
});
});
vs. your post, as follows...
);
};
},
error:function() {
response.error ("didn't work");
}
});
});
Map.prototype.updateMap = function (vehicles) {
nextVehicle:
for (var i = 0; i < vehicles.length; i++) {
for (var j = 0; j < this.oldVehicles.length; j++) {
var vehicle = vehicles[i];
var oldVehicle = this.oldVehicles[j];
if (vehicle.registration == oldVehicle.registration) {
oldVehicle.getPosition(function(latLng) {
if (vehicle.latitude != oldVehicle.lat) {
var newPos = new plugin.google.maps.LatLng(vehicle.latitude, vehicle.longitude);
oldVehicle.setPosition(newPos);
}
continue nextVehicle;
});
}
}
}
};
The code above does not work. I have a feeling this is to do with scope, I can't reach the nextVehicle label from inside the oldVehicle.getPosition method. How can I get around this?
Separate the matching logic from the update logic.
Map.prototype.updateMap = function (vehicles) {
// Only need to look up array lengths once
var vehiclesLength = vehicles.length,
oldVehiclesLength = this.oldVehicles.length;
for (var i = 0; i < vehiclesLength; i++) {
var vehicle = vehicles[i];
var oldVehicle = null;
// Find oldVehicle
for (var j = 0; j < oldVehiclesLength; j++) {
if (vehicle.registration == oldVehicle[j].registration) {
oldVehicle = oldVehicles[j];
break;
}
}
// Check for update if found
if (oldVehicle){
// Create closure for async callbacks
(function(oldV, lat,lng){
oldV.getPosition(function(latLng) {
if (lat != oldV.lat) {
var newPos = new plugin.google.maps.LatLng(lat,lng);
oldV.setPosition(newPos);
}
});
})(oldVehicle, vehicle.latitude, vehicle.longitude);
}
}
};
Just move the continue nextVehicle; line from inside the callback to immediately following the call to oldVehicle.getPosition(...):
Map.prototype.updateMap = function (vehicles) {
nextVehicle:
for (var i = 0; i < vehicles.length; i++) {
for (var j = 0; j < this.oldVehicles.length; j++) {
var vehicle = vehicles[i];
var oldVehicle = this.oldVehicles[j];
if (vehicle.registration == oldVehicle.registration) {
oldVehicle.getPosition(function(latLng) {
if (vehicle.latitude != oldVehicle.lat) {
var newPos = new plugin.google.maps.LatLng(vehicle.latitude, vehicle.longitude);
oldVehicle.setPosition(newPos);
}
});
continue nextVehicle;
}
}
}
};
This assumes the call to getPosition is a synchronous operation.
Edit:
Now if getPosition is asynchronous, you will need to use an asynchronous loop:
Something along this line might do the trick:
Map.prototype.updateMap = function (vehicles) {
var i = 0, j = -1, self = this;
var updatePosition = function() {
j++;
if (j == self.oldVehicles.length) {
j = 0;
i++;
}
if (i === vehicles.length) {
return; // We're done
}
var vehicle = vehicles[i];
var oldVehicle = self.oldVehicles[j];
if (vehicle.registration !== oldVehicle.registration) {
updatePosition();
}
else {
oldVehicle.getPosition(function(latLng) {
if (vehicle.latitude != oldVehicle.lat) {
var newPos = new plugin.google.maps.LatLng(vehicle.latitude, vehicle.longitude);
oldVehicle.setPosition(newPos);
updatePosition();
}
});
}
};
updatePosition();
};