function variables not defined error - javascript

I am calling a function in Javascript and passing few parameters(title, subTitle, text). I debugged and checked their values are being passed to it, I want to use them in a callback method but their values are not defined in that scope. How to solve this?
function geocodeQuery(query, title, subTitle, text) {
//If search manager is not defined, load the search module.
if (!searchManager) {
//Create an instance of the search manager and call the geocodeQuery function again.
Microsoft.Maps.loadModule('Microsoft.Maps.Search', function () {
searchManager = new Microsoft.Maps.Search.SearchManager(map);
geocodeQuery(query);
});
} else {
var searchRequest = {
where: query,
callback: function (r) {
//Add the first result to the map and zoom into it.
if (r && r.results && r.results.length > 0) {
var pin = new Microsoft.Maps.Pushpin(r.results[0].location,
{
title: title,
subTitle: subTitle,
text: text
});
map.entities.push(pin);
map.setView({ bounds: r.results[0].bestView });
}
},
errorCallback: function (e) {
//If there is an error, alert the user about it.
alert("No results found.");
}
};
//Make the geocode request.
searchManager.geocode(searchRequest);
}
}

Related

JS, Passing an argument to callback function (Bing maps)

Working with this example from Bing Maps V8
This line kicks off the map search: geocodeQuery("New York, NY");
This code fragment contains the callback function (which places the pin on the map):
var searchRequest = {
where: query,
callback: function (r) {
//Add the first result to the map and zoom into it.
if (r && r.results && r.results.length > 0) {
var pin = new Microsoft.Maps.Pushpin(r.results[0].location);
map.entities.push(pin);
map.setView({ bounds: r.results[0].bestView });
}
},
errorCallback: function (e) {
//If there is an error, alert the user about it.
alert("No results found.");
}
};
If I want to execute multiple searches, I can write:
geocodeQuery("New York, NY");
geocodeQuery("Queens, NY");
Now I have 2 pins on the map.
Next step: if I want to label the pins I'd extend the 'new pushpin code':
var pin = new Microsoft.Maps.Pushpin(r.results[0].location,
{
title: 'Queens',
text: '2'
});
Question:
The pins are placed by the callback function. Since I want each pin to have different text, how do I tweak this sample code so that I can pass new parameters to the callback function?
You would need to add an argument to the geocodeQuery function (maybe called title) and use that when you create the pin in the callback. Then you could simply call geocodeQuery("Queens, NY", "Queens")
function geocodeQuery(query, title) {
//If search manager is not defined, load the search module.
if (!searchManager) {
//Create an instance of the search manager and call the geocodeQuery function again.
Microsoft.Maps.loadModule('Microsoft.Maps.Search', function () {
searchManager = new Microsoft.Maps.Search.SearchManager(map);
geocodeQuery(query, title);
});
} else {
var searchRequest = {
where: query,
callback: function (r) {
//Add the first result to the map and zoom into it.
if (r && r.results && r.results.length > 0) {
var pin = new Microsoft.Maps.Pushpin(r.results[0].location, {
title: title,
text: '2'
});
map.entities.push(pin);
map.setView({ bounds: r.results[0].bestView });
}
},
errorCallback: function (e) {
//If there is an error, alert the user about it.
alert("No results found.");
}
};
//Make the geocode request.
searchManager.geocode(searchRequest);
}
}

Node.Js doesn't execute anonymous functions?? -aws lambda -alexa skill

I'm currently working on a Alexa Skill for my Smart Home.
I created a Lambda function and want to make a http request to a server. but it wont execute any of my anon. functions.
A lambda code example:
/* This code has been generated from your interaction model by skillinator.io
/* eslint-disable func-names */
/* eslint quote-props: ["error", "consistent"]*/
// There are three sections, Text Strings, Skill Code, and Helper Function(s).
// You can copy and paste the contents as the code for a new Lambda function, using the alexa-skill-kit-sdk-factskill template.
// This code includes helper functions for compatibility with versions of the SDK prior to 1.0.9, which includes the dialog directives.
// 1. Text strings =====================================================================================================
// Modify these strings and messages to change the behavior of your Lambda function
const request = require("request");
let speechOutput;
let reprompt;
let welcomeOutput = "Hallo xyz!";
let welcomeReprompt = "xy";
// 2. Skill Code =======================================================================================================
"use strict";
const Alexa = require('alexa-sdk');
const APP_ID = "my id"; // TODO replace with your app ID (OPTIONAL).
speechOutput = '';
const handlers = {
'LaunchRequest': function () {
this.emit(':ask', welcomeOutput, welcomeReprompt);
},
'AMAZON.HelpIntent': function () {
speechOutput = 'Placeholder response for AMAZON.HelpIntent.';
reprompt = '';
this.emit(':ask', speechOutput, reprompt);
},
'AMAZON.CancelIntent': function () {
speechOutput = 'Placeholder response for AMAZON.CancelIntent';
this.emit(':tell', speechOutput);
},
'AMAZON.StopIntent': function () {
speechOutput = 'Placeholder response for AMAZON.StopIntent.';
this.emit(':tell', speechOutput);
},
'SessionEndedRequest': function () {
speechOutput = '';
//this.emit(':saveState', true);//uncomment to save attributes to db on session end
this.emit(':tell', speechOutput);
},
'LichtIntent': function () {
//delegate to Alexa to collect all the required slot values
let filledSlots = delegateSlotCollection.call(this);
speechOutput = '';
//any intent slot variables are listed here for convenience
let zimmerSlotRaw = this.event.request.intent.slots.zimmer.value;
console.log(zimmerSlotRaw);
let zimmerSlot = resolveCanonical(this.event.request.intent.slots.zimmer);
console.log(zimmerSlot);
let was_lichtSlotRaw = this.event.request.intent.slots.was_licht.value;
console.log(was_lichtSlotRaw);
let was_lichtSlot = resolveCanonical(this.event.request.intent.slots.was_licht);
console.log(was_lichtSlot);
//THIS IS THE PART WHERE I NEED HELP!!
MakeRequest(function(data){
console.log("asddd");
speechOutput = "This is a place holder response for the intent named LichtIntent, which includes dialogs. This intent has 2 slots, which are zimmer, and was_licht. Anything else?";
var speechOutput = data;
this.emit(':ask', speechOutput, speechOutput);
});
console.log("asdww");
//DOWN TO HERE!!
},
'StromIntent': function () {
//delegate to Alexa to collect all the required slot values
let filledSlots = delegateSlotCollection.call(this);
speechOutput = '';
//any intent slot variables are listed here for convenience
let geraet_stromSlotRaw = this.event.request.intent.slots.geraet_strom.value;
console.log(geraet_stromSlotRaw);
let geraet_stromSlot = resolveCanonical(this.event.request.intent.slots.geraet_strom);
console.log(geraet_stromSlot);
let wasSlotRaw = this.event.request.intent.slots.was.value;
console.log(wasSlotRaw);
let wasSlot = resolveCanonical(this.event.request.intent.slots.was);
console.log(wasSlot);
//Your custom intent handling goes here
speechOutput = "This is a place holder response for the intent named StromIntent, which includes dialogs. This intent has 2 slots, which are geraet_strom, and was. Anything else?";
this.emit(':ask', speechOutput, speechOutput);
},
'FrageIntent': function () {
//delegate to Alexa to collect all the required slot values
let filledSlots = delegateSlotCollection.call(this);
speechOutput = '';
//any intent slot variables are listed here for convenience
let geraetSlotRaw = this.event.request.intent.slots.geraet.value;
console.log(geraetSlotRaw);
let geraetSlot = resolveCanonical(this.event.request.intent.slots.geraet);
console.log(geraetSlot);
let was_frageSlotRaw = this.event.request.intent.slots.was_frage.value;
console.log(was_frageSlotRaw);
let was_frageSlot = resolveCanonical(this.event.request.intent.slots.was_frage);
console.log(was_frageSlot);
//Your custom intent handling goes here
speechOutput = "This is a place holder response for the intent named FrageIntent, which includes dialogs. This intent has 2 slots, which are geraet, and was_frage. Anything else?";
this.emit(':ask', speechOutput, speechOutput);
},
'TuerIntent': function () {
//delegate to Alexa to collect all the required slot values
let filledSlots = delegateSlotCollection.call(this);
speechOutput = '';
//any intent slot variables are listed here for convenience
let zeitSlotRaw = this.event.request.intent.slots.zeit.value;
console.log(zeitSlotRaw);
let zeitSlot = resolveCanonical(this.event.request.intent.slots.zeit);
console.log(zeitSlot);
//Your custom intent handling goes here
speechOutput = "This is a place holder response for the intent named TuerIntent, which includes dialogs. This intent has one slot, which is zeit. Anything else?";
this.emit(':ask', speechOutput, speechOutput);
},
'Unhandled': function () {
speechOutput = "The skill didn't quite understand what you wanted. Do you want to try something else?";
this.emit(':ask', speechOutput, speechOutput);
}
};
exports.handler = (event, context) => {
const alexa = Alexa.handler(event, context);
alexa.appId = APP_ID;
// To enable string internationalization (i18n) features, set a resources object.
//alexa.resources = languageStrings;
alexa.registerHandlers(handlers);
//alexa.dynamoDBTableName = 'DYNAMODB_TABLE_NAME'; //uncomment this line to save attributes to DB
alexa.execute();
};
// END of Intent Handlers {} ========================================================================================
// 3. Helper Function =================================================================================================
//THESE ARE MY HELPER FUNCTIONS
function url(){
console.log("asd");
return " my server ip";
}
function MakeRequest(callback){
console.log("hallo!");
request.get(url(), function(error, response, body){
console.log("****************************************");
console.log(response);
console.log("****************************************");
console.log(error);
console.log("****************************************");
console.log(body);
console.log("****************************************");
callback("erfolg!");
});
console.log("hffggh");
}
//DOWN TO HERE!!
function resolveCanonical(slot){
//this function looks at the entity resolution part of request and returns the slot value if a synonyms is provided
let canonical;
try{
canonical = slot.resolutions.resolutionsPerAuthority[0].values[0].value.name;
}catch(err){
console.log(err.message);
canonical = slot.value;
};
return canonical;
};
function delegateSlotCollection(){
console.log("in delegateSlotCollection");
console.log("current dialogState: "+this.event.request.dialogState);
if (this.event.request.dialogState === "STARTED") {
console.log("in Beginning");
let updatedIntent= null;
// updatedIntent=this.event.request.intent;
//optionally pre-fill slots: update the intent object with slot values for which
//you have defaults, then return Dialog.Delegate with this updated intent
// in the updatedIntent property
//this.emit(":delegate", updatedIntent); //uncomment this is using ASK SDK 1.0.9 or newer
//this code is necessary if using ASK SDK versions prior to 1.0.9
if(this.isOverridden()) {
return;
}
this.handler.response = buildSpeechletResponse({
sessionAttributes: this.attributes,
directives: getDialogDirectives('Dialog.Delegate', updatedIntent, null),
shouldEndSession: false
});
this.emit(':responseReady', updatedIntent);
} else if (this.event.request.dialogState !== "COMPLETED") {
console.log("in not completed");
// return a Dialog.Delegate directive with no updatedIntent property.
//this.emit(":delegate"); //uncomment this is using ASK SDK 1.0.9 or newer
//this code necessary is using ASK SDK versions prior to 1.0.9
if(this.isOverridden()) {
return;
}
this.handler.response = buildSpeechletResponse({
sessionAttributes: this.attributes,
directives: getDialogDirectives('Dialog.Delegate', null, null),
shouldEndSession: false
});
this.emit(':responseReady');
} else {
console.log("in completed");
console.log("returning: "+ JSON.stringify(this.event.request.intent));
// Dialog is now complete and all required slots should be filled,
// so call your normal intent handler.
return this.event.request.intent;
}
}
function randomPhrase(array) {
// the argument is an array [] of words or phrases
let i = 0;
i = Math.floor(Math.random() * array.length);
return(array[i]);
}
function isSlotValid(request, slotName){
let slot = request.intent.slots[slotName];
//console.log("request = "+JSON.stringify(request)); //uncomment if you want to see the request
let slotValue;
//if we have a slot, get the text and store it into speechOutput
if (slot && slot.value) {
//we have a value in the slot
slotValue = slot.value.toLowerCase();
return slotValue;
} else {
//we didn't get a value in the slot.
return false;
}
}
//These functions are here to allow dialog directives to work with SDK versions prior to 1.0.9
//will be removed once Lambda templates are updated with the latest SDK
function createSpeechObject(optionsParam) {
if (optionsParam && optionsParam.type === 'SSML') {
return {
type: optionsParam.type,
ssml: optionsParam['speech']
};
} else {
return {
type: optionsParam.type || 'PlainText',
text: optionsParam['speech'] || optionsParam
};
}
}
function buildSpeechletResponse(options) {
let alexaResponse = {
shouldEndSession: options.shouldEndSession
};
if (options.output) {
alexaResponse.outputSpeech = createSpeechObject(options.output);
}
if (options.reprompt) {
alexaResponse.reprompt = {
outputSpeech: createSpeechObject(options.reprompt)
};
}
if (options.directives) {
alexaResponse.directives = options.directives;
}
if (options.cardTitle && options.cardContent) {
alexaResponse.card = {
type: 'Simple',
title: options.cardTitle,
content: options.cardContent
};
if(options.cardImage && (options.cardImage.smallImageUrl || options.cardImage.largeImageUrl)) {
alexaResponse.card.type = 'Standard';
alexaResponse.card['image'] = {};
delete alexaResponse.card.content;
alexaResponse.card.text = options.cardContent;
if(options.cardImage.smallImageUrl) {
alexaResponse.card.image['smallImageUrl'] = options.cardImage.smallImageUrl;
}
if(options.cardImage.largeImageUrl) {
alexaResponse.card.image['largeImageUrl'] = options.cardImage.largeImageUrl;
}
}
} else if (options.cardType === 'LinkAccount') {
alexaResponse.card = {
type: 'LinkAccount'
};
} else if (options.cardType === 'AskForPermissionsConsent') {
alexaResponse.card = {
type: 'AskForPermissionsConsent',
permissions: options.permissions
};
}
let returnResult = {
version: '1.0',
response: alexaResponse
};
if (options.sessionAttributes) {
returnResult.sessionAttributes = options.sessionAttributes;
}
return returnResult;
}
function getDialogDirectives(dialogType, updatedIntent, slotName) {
let directive = {
type: dialogType
};
if (dialogType === 'Dialog.ElicitSlot') {
directive.slotToElicit = slotName;
} else if (dialogType === 'Dialog.ConfirmSlot') {
directive.slotToConfirm = slotName;
}
if (updatedIntent) {
directive.updatedIntent = updatedIntent;
}
return [directive];
}
I use the "request" module for my http-request, I think you all know this module.
When I test my function, it gives me NO runtime error!
but the anonymous functions from the MakeRequest call and the request.get call wont execute, and I don't know why.
For Example the console output:
Hallo!,
Asd (very funny.. it gets the params for the request.get.. the bug has to be between the second param(the anon function itself?) in the call and the start of the anon function),
hffggh,
asdww
-the console.logs in the anon. functions doesn't show.
I maybe undestand why the MakeRequest funct. doesn't run -> because the callback from it never came. But why does the request.get not work?? I pasted the necessary parts (the MakeRequest and the helper functions) in a normal node projekt, and it worked!!? -facepalm.... im nearly crying..
My Goal: I want to receive a response from the server.. - thats all. But it just wont go into the function where I can access the response object(s).
(Scroll down to the helper functions)
Please help me out guys, I could really hit my head against the wall.
Reguards

Create a cell range output dynamically

In my add-in I am making an HTTP request and receiving an output. I want to place that output into a binding and have it expand the binding if necessary because the user won't necessarily know how many rows x columns the output will be. How would I go about doing this? Currently I am binding to a range, but if that range does not match the size of the [[]] that I am providing, then the data is not displayed in the sheet. So, this ends up requiring the user to know the size of the output.
What I'm doing currently using Angular is as follows (the problem with this being that the output isn't always the same size as the Office.BindingType.Matrix that the user selected in the spreadsheet):
I create the binding to where the output should be placed as follows:
inputBindFromPrompt(parameterId: number): Promise<IOfficeResult> {
let bindType: Office.BindingType;
if(this.inputBindings[parameterId].type != 'data.frame' && this.inputBindings[parameterId].type != 'vector') {
bindType = Office.BindingType.Text;
} else {
bindType = Office.BindingType.Matrix;
}
return new Promise((resolve, reject) => {
this.workbook.bindings.addFromPromptAsync(bindType, { id: this.inputBindings[parameterId].name },
(addBindingResult: Office.AsyncResult) => {
if(addBindingResult.status === Office.AsyncResultStatus.Failed) {
reject({
error: 'Unable to bind to workbook. Error: ' + addBindingResult.error.message
});
} else {
this.inputBindings[parameterId].binding = addBindingResult.value;
resolve({
success: 'Created binding ' + addBindingResult.value.type + ' on ' + addBindingResult.value.id
});
}
})
})
}
Then when the user submits via a button, the inputs are passed to a HTTP request service which then receives an output that I process into an array of arrays so that it can go into an Office.BindingType.Matrix:
this.isBusy = true;
this.feedback = 'submitted';
// Grab the values from the form
// Send as a POST and receive an output
// Put the output in the Excel sheet
this.webServicesService.postWebServices(this.service, this.inputParameters)
.subscribe(
(data: any) => {
// Correctly received data
// Access the data by name while looping through output parameters
this.error = false;
this.feedback = 'received data';
let i = 0;
this.outputParameters.forEach(element => {
// temporary name to identify the parameter
let name = element.name;
// Set the data value in the parameter
if(element.type == 'data.frame') {
let parameter = data[name];
this.feedback = parameter;
let excelData = [];
for(var key in parameter) {
if(parameter.hasOwnProperty(key)) {
var val = parameter[key];
excelData.push(val);
}
}
element.value = excelData;
}
else {
element.value = data[name];
}
// Set value in the form
let param = (<FormArray>this.serviceForm.controls['outputParameters']).at(i);
param.patchValue({
value: element.value
});
// Set value in the spreadsheet
this.excelService.outputSetText(i, element.value)
.then((result: IOfficeResult) => {
this.onResult(result);
i++;
});
}, (result: IOfficeResult) => {
this.onResult(result);
});
},
(error) => {
if(error.status == 400 || error.status == 401) {
// Return user to authentication page
this.authService.logout();
this.router.navigate(['/']);
} else {
// Tell user to try again
this.error = true;
}
}
);
The line above that is setting the value to the Office.Matrix.Binding is this.excelService.outputSetText(i, element.value), which calls this method in the Excel Service:
outputSetText(parameterId: number, data: any): Promise<IOfficeResult> {
return new Promise((resolve, reject) => {
if(this.outputBindings[parameterId].binding) {
this.outputBindings[parameterId].binding.setDataAsync(data, function (result: Office.AsyncResult) {
if(result.status == Office.AsyncResultStatus.Failed) {
reject({ error: 'Failed to set value. Error: ' + result.error.message });
} else {
let test: Office.Binding;
resolve({
success: 'successfully set value'
});
}
})
} else {
reject({
error: 'binding has not been created. bindFromPrompt must be called'
});
}
})
}
It's essentially using addFromPromptAsync() to set an output spot for the HTTP request. Then the user submits which sends the request, receives the data back and processes it into an array of arrays [[]] so that it can be the correct data format for Office.BindingType.Matrix. However, unless this is the same number of rows and columns as the binding originally selected, it won't display in the sheet. So, is there a binding type that will dynamically grow based on the data I give it? Or would I just need to release the current binding and make a new binding according to the size of the HTTP response data?
So long as you're using the "shared" (Office 2013) APIs, you will have this issue.
However, in the host-specific (2016+) APIs, you can easily solve the problem by resizing the range to suit your needs. Or more precisely, getting the binding, then asking for its range, then getting just the first (top-left) cell, and then resizing it:
await Excel.run(async (context) => {
let values = [
["", "Price"],
["Apple", 0.99],
["Orange", 1.59],
];
let firstCell = context.workbook.bindings.getItem("TestBinding").getRange().getCell(0, 0);
let fullRange = firstCell.getResizedRange(
values.length - 1, values[0].length - 1);
fullRange.values = values;
await context.sync();
});
You can try this snippet live in literally five clicks in the new Script Lab (https://aka.ms/getscriptlab). Simply install the Script Lab add-in (free), then choose "Import" in the navigation menu, and use the following GIST URL: https://gist.github.com/Zlatkovsky/5a2fc743bc9c8556d3eb3234e287d7f3. See more info about importing snippets to Script Lab.

Waiting to initialize untill data is loaded asynchronously

I am trying to design a personal app which loads data asynchronously and then displays a grid according to the windows 8.1 store apps.
i'm running into the issue that my ui is trying to execute before my data is loaded.
my current code:
(function () {
"use strict";
var asyncInProgress = true;
var groupedItems;
var list;
var observable;
var matches = new WinJS.Binding.List();
var matchGroups = new WinJS.Binding.List();
var BattleGrounds = new WinJS.Binding.List();
list = getData();
initGroups(list);
function initGroups(l) {
var groupedItems = list.createGrouped(
function groupKeySelector(item) { return item.group.key; },
function groupDataSelector(item) { return item.group; }
);
}
WinJS.Namespace.define("Data", {
Observable: WinJS.Class.define(function () {
this.dispatch = function () {
this.dispatchEvent("dataReady");
}
}),
getObservable: getObservable,
items: groupedItems,
groups: groupedItems.groups,
getItemReference: getItemReference,
getItemsFromGroup: getItemsFromGroup,
resolveGroupReference: resolveGroupReference,
resolveItemReference: resolveItemReference,
updateData: updateData,
getAsyncStatus: getAsyncStatus
});
WinJS.Class.mix(Data.Observable, WinJS.Utilities.eventMixin);
WinJS.Class.mix(Data.Observable, WinJS.Utilities.createEventProperties("dataReady"));
// Provides support for event listeners.
function getObservable() {
observable = new Data.Observable();
return observable;
}
// Get a reference for an item, using the group key and item title as a
// unique reference to the item that can be easily serialized.
function getItemReference(item) {
return [item.group.key, item.title, item.backgroundImage];
}
// This function returns a WinJS.Binding.List containing only the items
// that belong to the provided group.
function getItemsFromGroup(group) {
return list.createFiltered(function (item) { return item.group.key === group.key; });
}
// Get the unique group corresponding to the provided group key.
function resolveGroupReference(key) {
return groupedItems.groups.getItemFromKey(key).data;
}
// Get a unique item from the provided string array, which should contain a
// group key and an item title.
function resolveItemReference(reference) {
for (var i = 0; i < groupedItems.length; i++) {
var item = groupedItems.getAt(i);
if (item.group.key === reference[0] && item.title === reference[1]) {
return item;
}
}
}
function updateData() {
asyncInProgress = true;
BattleGrounds.splice(0, matches.length);
BattleGrounds._currentKey = 0;
groupedItems = null;
list = getData();
initGroups(list);
}
function getAsyncStatus() {
return asyncInProgress;
}
function getData() {
var darkGray = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsQAAA7EAZUrDhsAAAANSURBVBhXY3B0cPoPAANMAcOba1BlAAAAAElFTkSuQmCC";
var lightGray = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsQAAA7EAZUrDhsAAAANSURBVBhXY7h4+cp/AAhpA3h+ANDKAAAAAElFTkSuQmCC";
var mediumGray = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsQAAA7EAZUrDhsAAAANSURBVBhXY5g8dcZ/AAY/AsAlWFQ+AAAAAElFTkSuQmCC";
var url = 'https://api.guildwars2.com/v1/wvw/matches.json';
acquireSyndication(url).then(function (response) {
// Remove any invalid characters from JSONp response.
var fixedResponse = response.responseText.replace(/\\'/g, "'");
var jsonObj = JSON.parse(fixedResponse);
jsonObj.wvw_matches.forEach(function (battle) {
var anet_id = value.wvw_match_id;
// Create Group
var matchGroup = {
key: anet_id,
title: anet_id
};
matchGroups.push(matchGroup);
// Get Details
acquireSyndication("https://api.guildwars2.com/v1/wvw/match_details.json?match_id=" + anet_id).then(function (json) {
var fixedJson = json.responseText.replace(/\\'/g, "'");
var obj = JSON.parse(fixedJson);
fixedJson.maps.forEach(function (value) {
BattleGrounds.push({
group: matchGroup, key: matchGroup.title, title: value.type,
subtitle: value.type, map: "eb", description: "NA", content: "NA", "type": value.type,
"scores": value.scores, "objectives": value.objectives, "bonuses": value.bonuses, backgroundImage: lightGray
});
});
}, function (error) {
var x = error.getAllResponseHeaders();
var matchGroup = matchGroups[0];
for (var i = 0; i < matchGroups.length; i++) {
flickrPosts.push({
group: matchGroups[i], key: matchGroup.title, title: "Error loading",
subtitle: "Error", backgroundImage: lightGray, published: "N/A", description: "N/A"
});
}
asyncInProgress = false;
observable.dispatch();
});
});
}, function (error) {
var x = error.getAllResponseHeaders();
var matchGroup = matchGroups[0];
for (var i = 0; i < matchGroups.length; i++) {
flickrPosts.push({
group: matchGroups[i], key: matchGroup.title, title: "Error loading",
subtitle: "Error", backgroundImage: lightGray, published: "N/A", description: "N/A"
});
}
asyncInProgress = false;
observable.dispatch();
});
return BattleGrounds;
}
function acquireSyndication(url) {
return WinJS.xhr({
url: url,
headers: { "If-Modified-Since": "Mon, 27 Mar 1972 00:00:00 GMT" }
});
}
})();
This errors out on groups: groupedItems.groups. which says that groups is undefined.
i know this is because the data is still being processed.
How am i going to work around this?
i took a look at the promise object but the entire concept confuses me as i don't know enough about the infrastructure of a windows 8 app.
The core of your problem is in the getData() function - it is not returning your data because it uses asynchronous calls to get the data. The data is not yet available when it returns. It appears that that function makes several asynchronous calls to get data (using acquireSyndication()). When those asynchronous functions finish sometime in the future, you then put that data into matchGroups and then later into BattleGrounds after more calls to acquireSyndication().
What you're doing is quite messy so there isn't a simple fix. Conceptually, you need to process the BattleGrounds data from the completion handler of the asynchronous code and ALL code that uses it must continue from inside that completion handler, not after the getData() call. You cannot call getData() and use it like a synchronous function because it's asynchronous. This requires asynchronous programming techniques.
If you are doing multiple asynchronous calls and trying to carry out some action after all of them have completed (which I think is what you're doing), then you will need to code specifically for that condition too. You can either use promises or you can keep a counter of how many ajax calls there are and in each completion function, you increment the counter and see if this is the last one that just completed and, if so, then you can process all the data and continue executing the rest of your code.
I would also suggest that you don't use promises in one part of a function and then completion callbacks in the very next part. Use one of the other, not a mixture, to keep your code clean.

How to create a call back function and store the value of the variable

I am reading a Rss feed using setInterval method and displaying notification to the users ,I want to make sure I store the latest feed title so that the user does not get multiple notification of the same title again. The current implementation does not work because I cant use that variable until the response comes back. To make things worse I am delaying the execution.So I am guessing I need to use callback function get the value and do my checking inside that function. I am not able to figure out how to do the callback and get the value of entry_title.
/** global variable **/
var global_Rsstitle;
/** end global variable **/
function get_rss1_feeds() {
var Rss1_title = getRss("http://rss.cnn.com/rss/cnn_topstories.rss", function(entry_title) {
if(global_Rsstitle != entry_title)
global_Rsstitle = entry_title;
console.log('test',global_Rsstitle); // the value is outputed but global var is not working
});
console.log('test1',global_Rsstitle); // outputted as undefined ??
}
google.load("feeds", "1");
google.setOnLoadCallback(function () { setInterval(get_rss1_feeds, 5000); });
My jsRss.js
function getRss(url, callback){
if(url == null) return false;
// Our callback function, for when a feed is loaded.
function feedLoaded(result) {
if (!result.error) {
var entry = result.feed.entries[0];
var entry_title = entry.title; // need to get this value
callback && callback(entry_title);
}
}
function Load() {
// Create a feed instance that will grab feed.
var feed = new google.feeds.Feed(url);
// Calling load sends the request off. It requires a callback function.
feed.load(feedLoaded);
}
Load();
}
can u see the entry_title -> this stores d value i need
so i need to get this value n store it into a global variable
or send it to another fns as a argument
so that I can maintain the value
and when next time setInterval is fired
I get a new value so I can compare and check if its same
n if its same I dont display it to the user
google.load("feeds", "1");
google.setOnLoadCallback(function () {
var oldTitle = '',
newTitle = '',
getRss = function (url, callback) {
(url) && (function (url) {
var feed = new google.feeds.Feed(url);
feed.load(function (result) {
(!result.error && callback) && (callback(result.feed.entries[0].title));
});
}(url));
};
setInterval(function () {
getRss(
'http://rss.cnn.com/rss/cnn_topstories.rss',
function (title) {
newTitle = title;
if(oldTitle !== newTitle) {
oldTitle = newTitle;
console.log('oldTitle: ', oldTitle);
}
console.log('newTitle: ', newTitle);
}
);
}, 5000);
});

Categories

Resources