views:

236

answers:

2

Hi!

I want to do the following with my javascript codeblock.

  1. Handle all current and new device requests ie. detect,encrypt,decrypt,etc
  2. Return the result to the calling method

Questions

  1. How can I improve the existing code and get rid of the javascript strict warning:anonymous function does not always return a value.
  2. What is the right way of calling my method?

Any help is greatly appreciated

Thanks!

Herewith the code:

This is how I call the current method

//Contents of SmEditor.js
var response = Ext.decode(Prometheus.DeviceRequestHelper.detect(request_id));  


//contents of Sm.js
Ext.ns('myApp') 
myApp.DeviceRequestHelper = {  
    detect:function(request_id){  
        var task = function(){  
        Ext.Ajax.request({  
            url: 'device_requests.php',  
            params:{  
                action:'get_device', //in php  
                'request_id':request_id  
                },  
            timeout:30000, //30 seconds  
            success:function(response){//serverside response  
                var result = Ext.decode(response.responseText); //convert to js objects  
                if(result.success == true){//device was detected  
                    cons.log('success,device was detected');  
                    cons.log(result);  
                    Ext.TaskMgr.stop(runTask);  
                    return Ext.encode(result); //javascript strict warning  
                }else{  
                    if(runTask.taskRunCount >= 10){  
                        //retry limit exceeded  
                        Ext.Msg.show({  
                            title:'Server Failure',  
                            msg:"Detection Failed,Unable to detect device",  
                            icon: Ext.MessageBox.ERROR,  
                            buttons: Ext.Msg.OK  
                        });  
                        Ext.MessageBox.getDialog().getEl().setStyle('z-index','80000');  
                        Ext.TaskMgr.stop(runTask);  
                    }  
                }  
            },  
            failure:function(response){  
                Ext.TaskMgr.stop(runTask);  
                Ext.Msg.show({  
                    title:'Server Failure',  
                    msg:"Failed, server communication error",  
                    icon: Ext.MessageBox.ERROR,  
                    buttons: Ext.Msg.OK  
                });  
                Ext.MessageBox.getDialog().getEl().setStyle('z-index','80000');  
            }  
        })  
        }
        var runTask = {  
            run: task,  
            interval:2000,  
            repeat:10  
            };  
        Ext.TaskMgr.start(runTask);  
    }  
}    
A: 

First, Your detect method will not return a value and will return immediately(even before the ajax call completes) because the ajax call is asynchronous

Second, there's no point returning a value in your success handler. Instead you should provide a callback function to your detect method like so:

Ext.decode(Prometheus.DeviceRequestHelper.detect(request_id, function(response) {
      // do something with your response
}));

// detect function takes a callback function as a parameter
myApp.DeviceRequestHelper = {  
    detect:function(request_id, funCallback){  // pass in a callback function that is
                                               // called when result was a success
        var task = function(){  
           Ext.Ajax.request({  
               url: 'device_requests.php',  
               params:{  
                   action:'get_device', //in php  
                   'request_id':request_id  
                   },  
               timeout:30000, //30 seconds  
               success:function(response){//serverside response  
                   var result = Ext.decode(response.responseText); //convert to js objects  
                   if(result.success == true){//device was detected  
                       cons.log('success,device was detected');  
                       cons.log(result);  
                       Ext.TaskMgr.stop(runTask);  
                       // return Ext.encode(result); //javascript strict warning
                       funCallback(Ext.encode(result)); // ===========> callback function called.
                   }else{  
                       if(runTask.taskRunCount >= 10){  
                           //retry limit exceeded  
                           Ext.Msg.show({  
                               title:'Server Failure',  
                               msg:"Detection Failed,Unable to detect device",  
                               icon: Ext.MessageBox.ERROR,  
                               buttons: Ext.Msg.OK  
                           });  
                           Ext.MessageBox.getDialog().getEl().setStyle('z-index','80000');  
                           Ext.TaskMgr.stop(runTask);  
                       }  
                   }  
               },  
               failure:function(response){  
                   // ... failure handing code  
               }  
           });  
        }
        var runTask = {  
            run: task,  
            interval:2000,  
            repeat:10  
            };  
        Ext.TaskMgr.start(runTask);  
    }  
}
naikus
Thanks for your answer it's clear you and bobince are in agreement on using a callback function.Bobince gave me a detailed explanation why my code wont work.
Bosvark
A: 

To prevent this kind of warning, have the function return a value in all cases, or no cases. At the moment you're only returning a value in one if case; the other cases will not return anything. You can even return undefined to make the warning go away. However, what it is telling you is correct: that a function that sometimes has a return value and sometimes doesn't is a bit weird and suggests you're doing something wrong.

What you seem to want to do is have the inner return in the success method return a value from the detect() method. This is absolutely not possible. The inner function can only return a value to the caller of success, which is Prototype itself. By the time this happens, the detect() method has long since returned.

What you have here is asynchronous code. The detect() method can set up an AJAX request, but it must then return immediate to its caller, which will return control to the browser. At some later time, the HTTP request behind the AJAX call will complete, and then the success function will fire. JavaScript cannot call asynchronous code synchronously, or vice versa.

What you have to do is pass a callback function into your method, and then call it back on completion:

Prometheus.DeviceRequestHelper.detect(request_id, function(response) {
    // do something with `response`
});

myApp.DeviceRequestHelper= {  
    detect: function(request_id, callback) {
        ...
        Ext.Ajax.request({
            ...
            success: function(xhr) {
                var result= Ext.decode(xhr.responseText);
                if (result.success)
                    callback(result);
                ...
            },
            ...
        });
    },
    ...
 };

(I removed the extra Ext.encode->Ext.decode pair, that just seems like a waste of time.)

bobince
Great! Thank you for taking your time to answer my question.I will implement the changes and test the code before I mark the question as answered. Once again, Thanks!
Bosvark
Hi bobince, I implemented those changes but now I get 1 js error now - callback is not a function.What am I doing wrong?
Bosvark
Post the code you're using to call `detect()`... are you sure the `function() {...}` is inside the brackets as a second argument?
bobince
Thanks!!! SOLVED I forgot to put the function() in the brackets.I am getting the output I wanted :)
Bosvark