B4J Question [BANano] [SOLVED] Is it possible to create libraries that return the result of BANanoPromise?

Mashiane

Expert
Licensed User
Longtime User
Ola

I have a message BANanoObject that I can execute .RunMethod on. This returns a promise.

Is it possible directly from a class instance that will be compiled into a library, to have the promise execute and then I can only get the result. The result will be a string.

As an example... This call execute code on the BANanoObject. This is a promise call. I have to wait for it to execute so that I can get a result.

B4X:
private Sub getToken2 As String
    'define the vapidKey
    Dim opt As Map = CreateMap()
    opt.Put("vapidKey", key)
    'execute the promise
    Dim tThen As Object
    Dim tErr As Object
    Dim t As BANanoPromise = messaging.RunMethod("getToken", opt)
    t.Then(tThen)
    BANAno.ReturnThen(tThen)
    t.Else(tErr)
    BANAno.ReturnThen("")
    t.End
End Sub

Then when I want to get the token string, I can just call

B4X:
Dim token As String = instance.getToken
, which will execute the code below on the same class.

B4X:
Sub getToken As String
    Dim fbToken As String = ""
    Dim promToken As BANanoPromise
    promToken.CallSub(Me, "getToken2", Null)
    ' will pause your code here
    fbToken = BANAno.Await(promToken)
    Return fbToken
End Sub

Is this possible? If so how do I achieve it? I have ran the code and it returns a promise and not the string. Surely I'm missing something.

Thanks!
 
Last edited:

alwaysbusy

Expert
Licensed User
Longtime User
Again very difficult to answer with those snippets (no idea what messaging.RunMethod("getToken") does). My guess would be that the getToken() method should be called getTokenWait() because it has to be called async (it, or its called methods, use await functions, which include promises and fetches).

I'm aware this concept of promise/async/await is not easy to understand, as such a thing is typical JavaScript and does not really exist in B4J. That is why I avoided to go deeper into it here and just said if you make a call to a method that has to 'wait' for an answer, just add 'Wait' as a postfix to that methods name.

I see if I can make the transpiler smarter so you do not need to be aware of that anymore and it will make it async automatically if it detects await calls. The trick will be not to break existing code... ?

If you still are interested in the underlying JavaScript concept, this is a good read: https://javascript.info/async-await

Alwaysbusy
 
Upvote 0

Mashiane

Expert
Licensed User
Longtime User
Great and thanks for the link. At times one sees code like the showAvatar code in that link and does not even have any idea in terms of how to translate that into the Banano language.

Perhaps for clarity also, can you please convert that showAvatar code into Banano. One at least can look side by side that, this is the Javascript code, this is how you write it in Banano. You are right, it's confusing.

Thanks again.
 
Upvote 0

alwaysbusy

Expert
Licensed User
Longtime User
It really isn't that hard if you understand what the JavaScript does.

The 'so-much-as-possible-literal' translation:
B4X:
#if CSS
    .promise-avatar-example {
        width: 300px;
        height: 300px;
        border-radius: 50%;
    }
#End If

public Sub ShowAvatarWait() As Map
    
    Dim User As Map
    Dim response As BANanoFetchResponse
    Dim responseFetch As BANanoFetch
    
    ' read our JSON
    responseFetch.Initialize("https://javascript.info/article/promise-chaining/user.json",Null)
    response = BANano.Await(responseFetch)    
    User = BANano.Await(response.json)
    
    ' read github user (I'm here re-using the variables)
    responseFetch.Initialize("https://api.github.com/users/" & User.Get("name"),Null)
    response = BANano.Await(responseFetch)    
    User = BANano.Await(response.Json)
    
    ' show the avatar
    Dim body As BANanoElement
    body.Initialize("body")    
    
    Dim avatarURL As String = User.Get("avatar_url")
    Dim img As BANanoElement = body.Append($"<img id="avatar">"$).Get("#avatar")
    img.SetField("src", avatarURL)
    img.AddClass("promise-avatar-example")
    
    ' wait 3 seconds
    BANano.Sleep(3000)
        
    img.Remove
    
    Return User
End Sub

' HERE STARTS YOUR APP
Sub BANano_Ready()
    
    Dim user As Map = BANano.Await(ShowAvatarWait)
    Log(user)
end Sub

Of course, BANano has some nice shortcuts one can use for this example:

B4X:
public Sub ShowAvatarWait() As Map
    
    Dim User As Map
    
    ' read our JSON
    User = BANano.Await(BANano.GetFileAsJSON("https://javascript.info/article/promise-chaining/user.json", Null))
    
    ' read github user
    User = BANano.Await(BANano.GetFileAsJSON("https://api.github.com/users/" & User.Get("name"), Null))
    
    ' show the avatar
    Dim body As BANanoElement
    body.Initialize("body")    
    
    Dim avatarURL As String = User.Get("avatar_url")
    Dim img As BANanoElement = body.Append($"<img id="avatar" class="promise-avatar-example" src="${avatarURL}">"$).Get("#avatar")
    
    ' wait 3 seconds
    BANano.Sleep(3000)
        
    img.Remove
    
    Return User
End Sub

Alwaysbusy
 
Upvote 0

Mashiane

Expert
Licensed User
Longtime User
Wow I like these ..Wait calls a lot!

For that this implementation for my purposes works perfectly. Thanks a lot

B4X:
Sub subscribeToTopicsWait(topics As List) As Boolean
    Dim fetches As List
    fetches.Initialize
    For Each strtopic As String In topics
        Dim fetch As BANanoFetch = messaging.subscribe(strtopic)
        fetches.Add(fetch)
    Next
    Dim ResultsAll() As BANanoFetchResponse        'ignore
    ResultsAll = BANano.Await(BANano.PromiseAll(fetches))
    Return True
End Sub


Sub getSubscriptionsWait As Map
    Dim topicsM As Map
    Dim response As BANanoFetchResponse
    Dim fetch As BANanoFetch
   
    ' read our JSON
    fetch = messaging.GetSubscriptions
    response = BANano.Await(fetch)
    Dim res As Map = BANano.Await(response.json)
    Dim rel As Map = res.get("rel")
    topicsM = rel.Get("topics")
    Return topicsM
End Sub

Sub getTokenWait As String
    Dim token As String
    Dim fetch As BANanoFetch
    
    ' read our JSON
    fetch = firebase.messaging.getToken
    token = banano.Await(fetch)
    Return token
End Sub
 
Last edited:
Upvote 0
Top