Im working with jQuery. I have an app that makes ajax requests to server that responds with JSON.
in some cases the response from the server will indicate the name of a JS function to be called
{"responseType":"callback", "callback":"STUFF.TestCallback","callbackData":"this is in the callback"}
If the responseType is "callback" as above the JSON is passed to a function to handle this response type. (the var "response" contains the JSON above)
STUFF.callback = function(response){
if(typeof response.callback =='function'){
console.log("All Good")
response.callback(response);
}else{
console.log("Hmm... Cant find function",response.callback );
}
}
STUFF.TestCallBack = function(data){
alert("it worked");
}
But when I do this I get the error "response.callback is not a function".
Any comments on why this is not working and how to do this properly would be greatly appreciated.
A String is a String, not a Function.
response.callback() doesn't work because it is the same as "STUFF.TestCallback"() not STUFF.TestCallback()
You probably want to have the data structured something more like "callback": "TestCallback" then then do:
STUFF[response.callback](response);
Here you use the String to access a property of STUFF. (foo.bar and foo['bar'] being equivalent.)
You could transform that "namespace.func" into a call like this:
STUFF.callback = function(response) {
var fn = response.callback.split("."), func = window;
while(func && fn.length) { func = func[fn.shift()]; }
if(typeof func == 'function') {
console.log("All Good")
func(response);
} else{
console.log("Hmm... Cant find function", response.callback);
}
}
What this does it grab the function by getting window["STUFF"] then window["STUFF"]["TestCallback"] as it loops, checking if each level is defined as it goes to prevent error. Note that this works for any level function as well, for example "STUFF.One.Two.func" will work as well.
You propably could do
var myfunction = eval(response.callback);
myfunction(response);
although using eval() is considered as a bad style by some javascript developers.
Related
I am having problems with my Unity3D calling Firebase Functions function. My code is actually copied from https://firebase.google.com/docs/functions/callable.
My function code is following: (just copied this file actually)
https://github.com/firebase/quickstart-js/blob/a579893cfa33121952aeed9069c1554ed4e65b7e/functions/functions/index.js#L44-L50
and in Unity I have this:
//Create the arguments to the callable function.
var data = new Dictionary<string, object>();
data["text"] = "message";
data["push"] = true;
//Call the function and extract the operation from the result.
var function = FirebaseFunctions.DefaultInstance.GetHttpsCallable("addMessage");
function.CallAsync(data).ContinueWith((task) => {
if (task.IsFaulted)
{
foreach (var inner in task.Exception.InnerExceptions)
{
if (inner is FunctionsException)
{
Debug.Log(inner.Message);
}
}
}
else
{
Debug.Log("Finished: " + task.Result.Data);
}
});
But I am getting this result:
Response is not valid JSON object.
What am I doing wrong?
Thank you for your help!!!
I was still working on that problem and suddenly it worked. I dont know why to be honest, because the could looks exactely the same and I did not change anything on that.
I'm creating an Office Add-in and am having trouble with the javascript file.getFileAsync method in Word Online (Word 2013 desktop is fine).
I'm using sample code from github...
https://github.com/OfficeDev/office-js-docs/blob/master/docs/word/get-the-whole-document-from-an-add-in-for-powerpoint-or-word.md
My code looks like this...
function getFile() {
Office.context.document.getFileAsync(Office.FileType.Text,
{ sliceSize: 65536},
function (result) {
if (result.status == Office.AsyncResultStatus.Succeeded) {
// Get the File object from the result.
var myFile = result.value;
var state = {
file: myFile,
counter: 0,
sliceCount: myFile.sliceCount
};
getSlice(state);
}
});
}
function getSlice(state) {
state.file.getSliceAsync(state.counter, function (result) {
if (result.status == Office.AsyncResultStatus.Succeeded) {
sendSlice(result.value, state);
state.file.closeAsync();
}
else if(result.status == 'failed')
state.file.closeAsync();
});
}
Before calling file.getSliceAsync the data looks good - myFile.sliceCount is 1. The result function is never called and no errors are thrown in the console.
Thanks for any help you can provide!
UPDATE: this issue is fixed and live. Please try it again it must work now.
thanks!
---------------- ORIGINAL ANSWER JUST FOR REFERENCE ----------------------------
Yes, there is a regression right now in Word Online preventing the code to run successfully. The specific issue is that the file.getSliceAsync method is never calling the call-back function. This only happens with the TEXT type, if you want to get the docx or pdf this should work ok. This issue will be fixed in a couple of weeks.
You have an alternative if you want to get the text of the document you can use the new APIs for Word check out this sample:
Word.run(function(context) {
var myBody = context.document.body;
context.load(myBody);
return context.sync()
.then(function(){
console.log(myBody.text);
});
});
Hope this helps!
Thanks for reporting this issue!
Juan.
I'm working on a project which uses node and we're trying to achieve 100% coverage of our functions. This is the only function we haven't tested, and it's within another function.
var userInput = "";
req.on("data", function(data){
userInput += data;
});
How do you go about testing this function? We tried exporting the function from another file but no luck.
I should mention that we are using tape as a testing module.
You need to trigger this "data" event on req. So that this callback will be called.
For instance, let's suppose you have req on your test, you could do something like that (this is Mocha):
req.trigger('data', 'sampleData');
expect(userInput).to.equal('sampleData');
req.emit('data', {sampleData: 'wrongOrRightSampleDataHere'}) should do it.
When instantiating the http or hence the req object make sure you instantiate a new one, that no other test receives this event.
To be more complete...
var assert = require('assert')
function test() {
var hasBeenCalledAtLeastOnce = false
var userInput = "";
// req must be defined somewhere though
req.on("data", function(data){
userInput += data;
if(hasBeenCalledAtLeastOnce) {
assert.equal(userInput, "HelloWorld", "userInput is in fact 'HelloWorld'")
}
hasBeenCalledAtLeastOnce = true
});
req.emit('data', "Hello")
req.emit('data', "World")
}
test()
I know this question has been asked several times, but I couldn't seem to find a solution that worked for me in any of the previous questions. I have a variable that gets set when my HTML page is done loading, but sometimes when my code tries to access that variable, it says that it is undefined. I'm not sure why, since I believe I am waiting for everything to load properly. This exception seems to happen randomly, as most of the time all the code runs fine. Here's a simplified version of my code:
var globalVar;
function initStuff(filePath) {
// I wait till the HTML page is fully loaded before doing anything
$(document).ready(function(){
var video = document.getElementById("videoElementID");
// My parseFile() function seems to run smoothly
var arrayOfStuff = parseFile(filePath);
if (arrayOfStuff == null) {
console.error("Unable to properly parse the file.");
} else {
setGlobalVariable(arrayOfStuff);
video.addEventListener("play", updateVideoFrame, false);
}
});
}
function setGlobalVariable(arrayOfStuff) {
window.globalVar = arrayOfStuff;
}
function updateVideoFrame() {
// A bunch of other code happens first
// This is the line that fails occasionally, saying
// "window.globalVar[0].aProperty.anArray[0] is undefined"
var test = window.globalVar[0].aProperty.anArray[0].aProperty;
}
The only thing that I can think of that might be causing this problem is some sort of synchronicity issue. I don't see why that would be the case, though. Help please!
Edit:
In case the asynchronicity issue is coming from my parseFile(xmlFile) method, here is what I'm doing there. I thought it couldn't possibly be causing the issue, since I force the method to happen synchronously, but in case I'm wrong, here it is:
function parseKML(xmlFile) {
var arrayOfStuff = new Array();
// Turn the AJAX asynchronicity off for the following GET command
$.ajaxSetup( { async : false } );
// Open the XML file
$.get(xmlFile, {}, function(xml) {
var doc = $("Document", xml);
// Code for parsing the XML file is here
// arrayOfStuff() gets populated here
});
// Once I'm done processing the XML file, I turn asynchronicity back on, since that is AJAX's default state
$.ajaxSetup( { async : true } );
return arrayOfStuff;
}
The first thing you should do in your code is figure out which part of:
window.globalVar[0].aProperty.anArray[0]
is undefined.
Since you have multiple chained property references and array references, it could be many different places in the chain. I'd suggest either set a breakpoint right before your reference it examine what's in it or use several console.log() statement sto output each nested piece of the structure in order to find out where your problem is.
console.log("globalVar = " + globalVar);
console.log("globalVar[0] = " + globalVar[0]);
console.log("globalVar[0].aProperty = " + globalVar[0].aProperty);
console.log("globalVar[0].aProperty.anArray = " + globalVar[0].aProperty.anArray);
console.log("globalVar[0].aProperty.anArray[0] = " + globalVar[0].aProperty.anArray[0]);
If the problem is that globalVar isn't yet set, then you have a timing problem or an initialization problem.
If the problem is that one of the other properties isn't set, then you aren't initializing globalVar with what you think you are.
You may also want to write your code more defensibly so it fails gracefully if some of your data isn't set properly.
You need to use defensive programming.
http://www.javascriptref.com/pdf/ch23_ed2.pdf
Example:
var video = document.getElementById("videoElementID") || 0;
-
if( video && video.addEventListener ){
video.addEventListener("play", updateVideoFrame, false);
}
Here's another version of your code.
window.globalVar = globalVar || [];
function setGlobalVariable(arrayOfStuff) {
window.globalVar = arrayOfStuff;
}
function updateVideoFrame() {
// A bunch of other code happens first
// This is the line that fails occasionally, saying
// "window.globalVar[0].aProperty.anArray[0] is undefined"
if( window.globalVar ){
var g = window.globalVar || [];
var d = (g[0] || {})["aProperty"];
// etc...
}else{
console.error( "test error." );
}
}
function initStuff(filePath) {
// I wait till the HTML page is fully loaded before doing anything
$(document).ready(function () {
var video = $("#videoElementID");
// My parseFile() function seems to run smoothly
var arrayOfStuff = parseFile(filePath) || [];
if (arrayOfStuff == null || video == null ) {
console.error("Unable to properly parse the file.");
} else {
setGlobalVariable(arrayOfStuff);
video.bind("play", updateVideoFrame);
}
});
}
i have this function to retrieve json data from yql query
function link(b){
var jsonURI = "http://query.yahooapis.com/v1/public/yql?q="+encodeURIComponent("select href,alt,content from html where url='"+b+"' and xpath='//a[#id=\"download\"] |//img[#class=\"dvLinkOverlayFill\"] |//meta[#name=\"title\"]'")+"&format=json&diagnostics=true&_maxage=86400&callback=callback&jsoncallback=?";
jQuery.ajaxSetup({cache: true});
jQuery.getJSON(jsonURI,callback);
}
What i want is to check if the data is null or not before passing on to the callback, if its null, it runs again the link() function, if not it passes on, i have tried
if (jQuery.query.results == null){link(b);}
but no luck, any advice or guide?
EDIT: Got it working, part of it, by using
if (o.query.results == null) { link(b); }
inside the callback function
callback(o){
if (o.query.results == null) { link(b); }
However i can't pass the "b" from the link function to the callback function, it's the only thing that is left for this to work, something like callback(o,b) that could be passed on in here jQuery.getJSON(jsonURI,callback);
since this one is sending the "o", how to make it send the "b" aswell? something like
jQuery.getJSON(jsonURI,callback(o,b));
EDIT updated question answer:
function link(b){
var jsonURI = "http://query.yahooapis.com/v1/public/yql?q="+encodeURIComponent("select href,alt,content from html where url='"+b+"' and xpath='//a[#id=\"download\"] |//img[#class=\"dvLinkOverlayFill\"] |//meta[#name=\"title\"]'")+"&format=json&diagnostics=true&_maxage=86400&callback=callback&jsoncallback=?";
jQuery.ajaxSetup({cache: true});
jQuery.getJSON(jsonURI,function(data, status, xhr){
callback(data, status, xhr,b);
});
}
So you got ur b object in arguments[3]
Couldn't you just simplify that?
if (!jQuery.query.results) { link(b); }