0

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();
    }
});
Makyen
  • 31,849
  • 12
  • 86
  • 121
user2881430
  • 367
  • 1
  • 5
  • 17
  • Possible duplicate of [How do I return the response from an asynchronous call?](http://stackoverflow.com/questions/14220321/how-do-i-return-the-response-from-an-asynchronous-call) – Makyen Sep 27 '16 at 19:45
  • As written, `assignurl=urls.URL(...` executes well after `url: assignurl,`. Thus, when you `assign.get();` the url is whatever it was prior to the execution of the code shown (i.e. invalid). – Makyen Sep 27 '16 at 20:13
  • @Makyen may be I'm asking a silly question, however i don't get it how would i do that? – user2881430 Sep 27 '16 at 20:20

1 Answers1

1

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.

Makyen
  • 31,849
  • 12
  • 86
  • 121
  • Thanx @Makyen I solved the issue and yes that `fetch.get()` called when addon initialized – user2881430 Sep 27 '16 at 21:03
  • @user2881430, I have updated the code to something that might actually work (previously, the first code block would produce the same error). I had erroneously relied on my reading of your Question to indicate that the error only occurs within `fetch`'s `onCompletion` handler when it is actually occurring when `var assign = Request({` is executed with an invalid `assignurl`. The probable confusion is that you got `fetch` working then added `assign` at which point the error started showing up (or that is my guess as to the order of things accounting for when the error actually is thrown). – Makyen Sep 27 '16 at 21:39