How does one return data to the original caller fu

2019-01-25 23:35发布

I have a problem returning data back to the function I want it returned to. Code below:

function ioServer(request_data, callback)
{
    $.ajax({
        cache: false,
        data: "request=" + request_data,
        dataType: "json",
        error: function(XMLHttpRequest, textStatus, errorThrown){},
        success: function(response_data, textStatus){
            callback(response_data);
            },
        timeout: 5000,
        type: "POST",
        url: "/portal/index.php/async"
    });
}   

function processRequest(command, item, properties)
{
    var request = {};
    request.command = command;
    request.item = item;
    request.properties = properties;
    var toServer = JSON.stringify(request); 
    var id = ioServer(toServer, processResponse);
    return id;
}

function processResponse(fromServer)
{
    if (fromServer.response == 1)
    {
        return fromServer.id;   
    }   
}

I invoke this piece of code by calling the processRequest function inside another function. Sending the request and retrieving the response works just fine. However, I need to return a value 'id' from the response back to the processRequest function, so it in turn can return that value to its caller. As far as I can follow, the return in processResponse returns to $.ajax, but I need it to return further back to processRequest.

BTW the if statement in processResponse refers to a value set by the server-side PHP script to tell whether the request was allowed (for instance if the user was not logged in, fromServer.response would be 0). It does not have anything to do with the success/error routines of the $.ajax object.

Many thanks for the help.

@Jani: Thanks for the response, but could you clarify a bit more? The function where 'id' is needed has the following code:

$(#tabs).tabs('add', '#tab-' + id, 'New tab');

Are you saying I should try to execute this piece of code in the processResponse function? Because that is not what I intented to do; these function are meant to be an all-purpose solution to maintain state server-side. That is why I avoided placing this piece of code there.

5条回答
劳资没心,怎么记你
2楼-- · 2019-01-26 00:14

As Tony didn't provide any comments, let me add details about what he is suggesting.

As you have learned, the processRequest function completes as soon as $.ajax call is made because $.ajax method is asynchronous. So how would you notify the caller of processRequest that the task is done?

Simple, you ask that the caller of processRequest to supply a 'callback function'. The processRequest will call this function whenever it has received the ajax output. In tony's code, this is the last argument to the processRequest function.

So your calling code will now look like

function tabMethod()
{
     processRequest('command', 'item', 'properties', 
                  function(id)
                  {
                     if(id == null) 
                     {
                          alert('There is a problem!');
                          return;
                     }
                     $('#tabs').tabs('add', '#tab-' + id, 'New tab');
                  });


};
查看更多
乱世女痞
3楼-- · 2019-01-26 00:14

Since this is an asynchronous request, it does not directly return a value like that and it isn't possible.

The way to approach this is to have some method which performs any actions you need on the fetched data, instead of attempting to have a return value which will not work.

查看更多
做自己的国王
4楼-- · 2019-01-26 00:15

Instead of implementing blocking to simulate a synchronous call like someone else previously posted, just make the AJAX call itself synchronous and update your success wrapper:

function ioServer(request_data, callback) {
    var response = null;
    $.ajax({
        cache: false,
        data: "request=" + request_data,
        dataType: "json",
        error: function(XMLHttpRequest, textStatus, errorThrown){},
        success: function(response_data, textStatus) {
                response = callback(response_data);
        },
        timeout: 5000,
        type: "POST",
        url: "/portal/index.php/async",
        async: false
    });

    return response;
}

Edit: Although useful, this is sorta against the grain of "normal" AJAX use. I would suggest changing your approach instead.

查看更多
闹够了就滚
5楼-- · 2019-01-26 00:37

I think maybe this is closer to what you are looking for...

function ioServer(request_data, callback)
{
    $.ajax({
        cache: false,
        data: "request=" + request_data,
        dataType: "json",
        error: function(XMLHttpRequest, textStatus, errorThrown){},
        success: function(response_data, textStatus){
                processResponse(response_data, callback);
                },
        timeout: 5000,
        type: "POST",
        url: "/portal/index.php/async"
    });
}   

function processRequest(command, item, properties, callback)
{
    var request = {};
    request.command = command;
    request.item = item;
    request.properties = properties;
    var toServer = JSON.stringify(request); 
    ioServer(toServer, callback);
}

//internal callback to handle response code
function processResponse(fromServer, callback)
{
    if (fromServer.response == 1)
    {
        //call the callback with the id
        callback(fromServer.id);   
    }   
    else
    {
        //You have to remember to call the callback no matter what
        //or the caller won't know when it's complete
        callback(null);  //or some other "didn't get a valid response" value
    } 
}
查看更多
做自己的国王
6楼-- · 2019-01-26 00:40

Awesome! Thank you guys for the help, it works like a charm now. And I've learned to use callbacks better. Here's the full working code:

createTab('#tabs'); // I'm using JQuery UI to handle tabs    

function createTab(parent_element){
            var name = {};
            name.name = "New tab";
            var position = {};
            position.position = $(parent_element).tabs('length') + 1;
            var properties = new Array();
            properties[0] = name;
            properties[1] = position;
            processRequest(1, 1, properties, 
                      function(id)
                      {
                         if(id == null) 
                         {
                              alert('There is a problem!');
                              return;
                         }
                         $('#tabs').tabs('add', '#tab-' + id, 'New tab');
                      });
        }

function ioServer(request_data, callback)
{
    $.ajax({
        cache: false,
        data: "request=" + request_data,
        dataType: "json",
        error: function(XMLHttpRequest, textStatus, errorThrown){},
        success: function(response_data, textStatus){
                processResponse(response_data, callback);
                },
        timeout: 5000,
        type: "POST",
        url: "/portal/index.php/async"
    });
}   

function processRequest(command, item, properties, callback)
{
    var request = {};
    request.command = command;
    request.item = item;
    request.properties = properties;
    var toServer = JSON.stringify(request); 
    ioServer(toServer, callback);
}

//internal callback to handle response code
function processResponse(fromServer, callback)
{
    if (fromServer.response == 1)
    {
        //call the callback with the id
        callback(fromServer.id);   
    }   
    else
    {
        //You have to remember to call the callback no matter what
        //or the caller won't know when it's complete
        callback(null);  //or some other "didn't get a valid response" value
    } 
}

And it adds a new tab at the end of the list in the page. This is now also stored server-side with PHP and MySQL, just like I wanted it.

Thanks again!

查看更多
登录 后发表回答