user2881430 user2881430 - 2 months ago 5
Javascript Question

How to pass Variable to Request API in Mozilla Add-on SDK extension?

I'm trying to pass the variable value to the Request API of a Mozilla Add-on SDK extension.

In the code below, the

fetch
Request
is working. However, when I try requesting another
Request
(
assign
) in the
onCompletion
handler for
fetch
, it says:

RequirementError: The option "url" is invalid.


How can use the URL I have in the
onCompletion
handler for the
fetch
Request
for the URL in the
assign
Request
?

var fetch = Request({
url: 'http://itildemo.servicedeskplus.com/sdpapi/request?INPUT_DATA={%22operation%22:{%22details%22:{%22status%22:%22open%22,%22from%22:0,%22limit%22:500,%22filterby%22:%22Unassigned_System%22}}}&OPERATION_NAME=GET_REQUESTS&TECHNICIAN_KEY=07109ADB-E642-4F46-917C-CA60F89CE6DC&format=json',
overrideMimeType: "text/plain; charset=latin1",
onComplete: function (response) {
workorder_id=JSON.parse(response.text).operation.details;
if(workorder_id!=null){
assignurl=urls.URL('http://itildemo.servicedeskplus.com/sdpapi/request/'+workorder_id[0].WORKORDERID+'?OPERATION_NAME=EDIT_REQUEST&TECHNICIAN_KEY=07109ADB-E642-4F46-917C-CA60F89CE6DC&INPUT_DATA= <Details><parameter><name>technician</name><value>'+technician_id[0].NAME+'</value></parameter></Details>');
console.log(assignurl);
assign.get();}
else{fetch.get();}
}
});

var assign = Request({
url: assignurl,
overrideMimeType: "text/plain; charset=latin1",
onComplete: function (response) {
var o=technician_id[0];
for (var k = 0; k < technician_id.length; k++) {
if (technician_id.length - 1 == k) {
technician_id[k] = o;
} else {
technician_id[k] = technician_id[k + 1];
};
};
fetch.get();
}
});

Answer

You are confused by the order of execution of your asynchronous code.

As it is written,

var assign = Request({
    url: assignurl,

executes well before your callback function executes the line providing your assignurl:

assignurl=urls.URL('http:// ...

By calling the Request() constructor, (var assign = Request({), you have assigned the url as assignurl existed at that time. Changing the variable assignurl after that point has no affect on the assign Request. Thus, you either need to change the assign.url, or create the request after you have the URL available.

NOTE: The url parameter must be present and valid when you call the Request constructor. Thus, I am assuming that your question is incorrect in stating that the error:

RequirementError: The option "url" is invalid.

only happens from within onCompletion handler for fetch. It should have happened when you executed the var assign = Request({url:asignurl with an invalid assignurl.

There are multiple ways you can change your code to use the URL which you now have (from with the fetch onComplete callback) in the Request which you are creating for assign. Which method you use will depend on if you are going to use the a very similar request to that you use for assign in more than one place within your code.

One possible change would be to move the creation of the assign Request into the onCompletion handler for fetch:

var Request = require("sdk/request").Request;
var assignurl;          //Unknown from Question
var technician_id=[];   //Unknown from Question
var workorder_id;       //Unknown from Question

var assign;
var fetch = Request({
    url: 'http://itildemo.servicedeskplus.com/sdpapi/request?INPUT_DATA={%22operation%22:{%22details%22:{%22status%22:%22open%22,%22from%22:0,%22limit%22:500,%22filterby%22:%22Unassigned_System%22}}}&OPERATION_NAME=GET_REQUESTS&TECHNICIAN_KEY=07109ADB-E642-4F46-917C-CA60F89CE6DC&format=json',
    overrideMimeType: "text/plain; charset=latin1",
    onComplete: function (response) {
        workorder_id=JSON.parse(response.text).operation.details;
        if(workorder_id!=null){
            assignurl=urls.URL('http://itildemo.servicedeskplus.com/sdpapi/request/'+workorder_id[0].WORKORDERID+'?OPERATION_NAME=EDIT_REQUEST&TECHNICIAN_KEY=07109ADB-E642-4F46-917C-CA60F89CE6DC&INPUT_DATA= <Details><parameter><name>technician</name><value>'+technician_id[0].NAME+'</value></parameter></Details>');
            assign = Request({
                url: assignurl,
                overrideMimeType: "text/plain; charset=latin1",
                onComplete: function (response) {
                    var o=technician_id[0];
                    for (var k = 0; k < technician_id.length; k++) {
                        if (technician_id.length - 1 == k) {
                            technician_id[k] = o;
                        } else {
                            technician_id[k] = technician_id[k + 1];
                        };
                    };
                    fetch.get(); //This will throw an error (see below).  Even if it
                                 //  worked it is recursive, which is probably not
                                 //  what you desire.
                }
            });
            console.log(assign.url);
            assign.get();}
        else{
            fetch.get(); //This should always throw an error as you are attempting to
                         //  re-use the Request. In other words, the only way to get
                         //  here is if you have already done fetch.get() once
                         //  and reusing the Request throws an error. 
        }
    }
});

If you might issue multiple assign requests, you could structure your code such that creating the assign Request is encapsulated within a function which you could call multiple times to create multiple very similar requests, should you have need of doing so elsewhere in your code:

var Request = require("sdk/request").Request;
var technician_id=[];   //Unknown from Question
var workorder_id;       //Unknown from Question

var assign;
var fetch = Request({
    url: 'http://itildemo.servicedeskplus.com/sdpapi/request?INPUT_DATA={%22operation%22:{%22details%22:{%22status%22:%22open%22,%22from%22:0,%22limit%22:500,%22filterby%22:%22Unassigned_System%22}}}&OPERATION_NAME=GET_REQUESTS&TECHNICIAN_KEY=07109ADB-E642-4F46-917C-CA60F89CE6DC&format=json',
    overrideMimeType: "text/plain; charset=latin1",
    onComplete: function (response) {
        workorder_id=JSON.parse(response.text).operation.details;
        if(workorder_id!=null){
            assign = setupAssignRequest(urls.URL('http://itildemo.servicedeskplus.com/sdpapi/request/'+workorder_id[0].WORKORDERID+'?OPERATION_NAME=EDIT_REQUEST&TECHNICIAN_KEY=07109ADB-E642-4F46-917C-CA60F89CE6DC&INPUT_DATA= <Details><parameter><name>technician</name><value>'+technician_id[0].NAME+'</value></parameter></Details>'));
            console.log(assign.url);
            assign.get();}
        else{
            fetch.get(); //As stated above, this should always throw an error.
        }
    }
});

function setupAssignRequest(assignurl) {
    return Request({
        url: assignurl,
        overrideMimeType: "text/plain; charset=latin1",
        onComplete: function (response) {
            var o=technician_id[0];
            for (var k = 0; k < technician_id.length; k++) {
                if (technician_id.length - 1 == k) {
                    technician_id[k] = o;
                } else {
                    technician_id[k] = technician_id[k + 1];
                };
            };
            fetch.get(); //If the only code you have is what is shown, this will
                         // throw an error. It is possible that "fetch" has been 
                         // re-initialized with a new call to Request elsewhere
                         // in your code.
        }
    });
}

Regarding the fetch.get(); within your fetch's onComplete handler: Trying to do this should always result in throwing an error. The only way to get to that code is to have already called fetch.get(); and each Request can only be used once:

Each Request object is designed to be used once. Attempts to reuse them will throw an error.