Search code examples
javascriptfirefox-addonmozilla

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();
    }
});

Solution

  • 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.