Why do I need to return the value outside the request when using sync requests?
I have a question about sync requests.
Background: I need to get the userID of the user immediately before checkout. If userID is null or zero I will force the user to login. I decided to use the synchronous request. I understand the difference between async and sync requests. However I don't understand why the first code below does not work, but the second does.
...
UserId = GetUserId();
...
function GetUserId()
{
var jsonRequest = new Request({url: myurl, async: false, onComplete: function(result) {return result;}}).get();
}
When I use the code above, I get UserId = undefined. However it works when I use the code below
...
UserId = GetUserId();
...
function GetUserId()
{
var resultreturned;
var jsonRequest = new Request({url: myurl, async: false, onComplete: function(result) {resultreturned = result;}开发者_运维知识库}).get();
return resultreturned;
}
It seems to me that in the first code, the processing does not stop even though I used the async:false. In the second code it works.
Does anyone know why?
In addition, is there a way to access the returned id without using the var resultreturned? Can I access the return using something like
return jsonRequest.value or jsonRequest.result or something else?
Thank you.
The first version of GetUserId
doesn't return anything. Simple as that. That the anonymous function passed as the completion handler returns something doesn't matter; its return value is passed to some internal mootools function and is ignored.
As for accessing the result, the base XMLHttpRequest object should be accessible as the xhr
property of the Request object (though this doesn't appear to be part of Request's public interface), and the response (in turn) is accessible as the responseText
property of the XHR object. In short, try:
jsonRequest.xhr.responseText
However, this shouldn't be necessary. Any synchronous request can be turned into an asynchronous request by passing along a callback to run when the request completes. The function you pass as the onComplete
argument is an example of this. This has the technical name of "continuation passing" (a "continuation" is, somewhat informally, "the rest of the calculation, from a give point forward").
Forget about call stacks for a moment. Pretend the return
statement as just another function. This return
function is a continuation; when it's called, the rest of the calculation happens. The first step in switching to asynchronous calls is to have your GetUserId
function call the continuation passed in instead of special return
continuation.
function GetUserId(succeed, fail)
{
var resultreturned;
var jsonRequest = new Request({url: myurl, async: false, onSuccess: function(result) {resultreturned = result;}, onFailure: fail}).get();
succeed(resultreturned);
}
To finish the switch, pass the continuation on to Request
rather than invoking it in GetUserId
, and make the request asynchronous.
function GetUserId(succeed, fail)
{
new Request({url: myurl, onSuccess: succeed, onFailure: fail}).get();
}
...
function checkoutOrLogin(userId, responseXML) {
if (userId) {
/* continue checkout */
} else {
/* display login form */
}
}
GetUserId(checkoutOrLogin, function(xhr) {/* display error message */});
The problem is of the scope. In the case of the first example, you are returning value from an annonymous function that is not assigned to any variable.
精彩评论