Forum Discussion

rjbrown's avatar
rjbrown
Visitor
13 years ago

Async http requests

I'm trying to do async requests for a text files while a video is playing, but my simple test won't work, it always gets a response code of -10001, and the string is empty. The test url should (and does, when tested from a browser) return a simple text file.

I start the request using the function below, passing it the port that is also monitoring various video events (I'm calling it at some point while the video is already playing):

Function startAsyncRequest(port)
print "startAsyncRequest"
urlXfer = CreateObject("roURLTransfer")
urlXfer.setUrl("http://192.168.1.200/test123.txt")
urlXfer.setPort(port)
urlXfer.EnableEncodings(true)
if urlXfer.asyncGetToString() = true
print "successful asynchGetToString"
end if
end Function


Then, I call the below function at the appropriate part of the loop. It does get triggered (right after I called the function to make the request), and I see from the server logs that it has properly requested the file from my server.

Function showAsyncResult (msg)
if type(msg) = "roUrlEvent"
print "showAsynchResult"
print str(msg.GetResponseCode())
print "[" + msg.GetString() + "]"
end if
end Function


Here is what prints out:

startAsyncRequest
successful asynchGetToString
showAsynchResult
-10001
[]


What am I doing wrong here? Obviously -10001 is not a valid http response code.

Thanks,
-rob
  • You need to create your roUrlTransfer object at a higher scope (maybe in the function with the wait loop). Currently, it's leaving scope as soon as you exit the startAsyncRequest function. Once it goes out of scope, it's gone, so you won't be able to get anything worthwhile from the message port.
  • Wow that's weird. I would have expected it the object to stick around since the port is referencing it, but I guess Brightscript is a different animal than the languages I'm more used to (i.e. javascript/java/etc)

    Anyway, thanks much for the answer.
  • "rjbrown" wrote:
    Wow that's weird. I would have expected it the object to stick around since the port is referencing it, but I guess Brightscript is a different animal than the languages I'm more used to (i.e. javascript/java/etc)

    Anyway, thanks much for the answer.

    It's referencing the port, not the other way around.
  • It's referencing the port, not the other way around.


    Well yeah, technically that's true, but then again I would've thought the setPort function would cause the port to also store a back reference to the roUrlTransfer. Or at least something (the networking module?) would store a reference to any objects that are actively involved in a current network transaction.

    I guess my point is that in most garbage-collected languages you don't have to worry about that sort of thing, because if anything has a reference to an object it won't be deallocated, and if nothing has a reference to an object, the object can no longer be functionally part of the program, so it doesn't matter if it is deallocated. Obviously Brightscript is different in that regard, since you have to take explicit steps to make sure something doesn't get deallocated when it is still in use. This is almost reminiscent of creating an object on the stack in C or C++.

    Anyway, I've now read up on how Brightscript's garbage collection works, and I'll watch out for this sort of thing. Thanks for your help.
  • Since I didn't see any good examples of async requests, here's a reworking of the two functions so they are generally useful, in case anyone is interested. I made them so you can have multiple async requests happening at the same time and they won't conflict.

    ' url: the url
    ' port: port that is being monitored with wait()
    ' return value: the unique id of the request (or 0 for failure).
    Function sendAsyncRequest(url as String, port as Object) as Integer
    if m.asynchRequests = invalid
    m.asynchRequests = {}
    end if

    urlXfer = CreateObject("roURLTransfer")
    urlXfer.setUrl(url)
    urlXfer.setPort(port)
    urlXfer.EnableEncodings(true)
    if urlXfer.asyncGetToString() = false
    return 0
    end if
    id = urlXfer.GetIdentity()
    m.asynchRequests[str(id)] = urlXfer
    return id
    end Function

    and...

    ' msg: the message returned from wait()
    ' id: (optional) it will ignore responses with different ids
    ' return value: invalid, if not an async request or not the right id, or
    ' an object with the string (as "data") and the id,
    ' and the response code (hopefully 200)
    Function getAsyncResponse (msg as Object, id = 0 as Integer) as Object
    if type(msg) = "roUrlEvent"
    currId = msg.GetSourceIdentity()
    if id = 0 or id = currId
    out = {
    data : msg.GetString()
    id : currId
    responseCode : msg.GetResponseCode()
    }
    m.asynchRequests.delete(str(currId))
    return out
    end if
    end if
    return invalid
    end Function