B4J Tutorial [BANano] Working with promises

Discussion in 'B4J Tutorials' started by alwaysbusy, Feb 7, 2019.

  1. alwaysbusy

    alwaysbusy Expert Licensed User

    BANano 2.19+ has a new object: BANanoPromise. It allows you to easily use Javascript Promises.

    A promise can be useful e.g. if you want to upload/download files, which can take some time to do. It is comparable with B4Js Wait For.

    This is probably the easiest to understand explanation of a Promise I could find on the interweb:

    ---------------------------------------------------
    A Promise in short:

    "Imagine you are a kid. Your mom promises you that she'll get you a new phone next week."

    You don't know if you will get that phone until next week. Your mom can either really buy you a brand new phone, or stand you up and withhold the phone if she is not happy :(.

    That is a promise. A promise has 3 states. They are:
    1. Pending: You don't know if you will get that phone
    2. Fulfilled: Mom is happy, she buys you a brand new phone
    3. Rejected: Your mom is happy, she withholds the phone
    ----------------------------------------------------
    From: https://scotch.io/tutorials/javascript-promises-for-dummies
    It is a very good read if you are new to Promises.

    The source code of this tutorial, with comments, can be found in the zip (the Promises folder).

    BASIC STRUCTURE:
    Code:
    ' the promise itself
    Dim promise As BANanoPromise
    ' the results from the promise
    Dim Result As Map
    Dim Error As String
                     
    ' call a method 
    promise.CallSub(Module, "MethodName"Array(Param1, Param2, ...))

    ' if success         
    promise.Then(Result)
    ' or in case you use Wait or Sleep methods in the success branch
    promise.ThenWait(Result)
    ' if an error
    promise.Else(Error)
    ' or in case you use Wait or Sleep methods in the error branch
    promise.ElseWait(Error)
    ' closing a promise
    promise.End
    So for example letting the user upload files would look like this:
    Code:
    ' get all the files selected from the input #fu
    Dim UploadedFiles() As String = BANano.GetElement("#fu").GetField("files").Result
         
    ' make a promise that will show "Done" if ALL file all uploaded
    Dim promise As BANanoPromise
    ' the results from the promise
    Dim Result As Map
    Dim Error As String
                     
    ' call the UploadAll method 
    promise.CallSub(Me, "UploadAllFiles"Array(UploadedFiles))
             
    ' when it is done, we can use whatever the UploadAll has returned in its BANano.ReturnThen call 
    promise.Then(Result)
        
    ' let's show all our urls
        For i = 0 To Result.Size - 1
           
    Log(Result.GetKeyAt(i) & "=" & Result.GetValueAt(i))
        
    Next 
    promise.Else(Error)
        
    Log("Error: " & Error)     
    promise.End
    Methods called using Promise.CallSub (+all methods called in it and further on) do not use the normal Return! Instead, one can use one of these two methods:
    Code:
    ' returns to the above promise.Then (or .promise.ThenWait)
    BANano.ReturnThen(result)
    ' returns to the above promise.Else (or .primise.ElseWait)
    BANano.ReturnElse(error)
    Promises can be chained. For example in the demo, once we have all the upload files, we do a http request to get some json:
    Code:
    ' make a promise that will show "Done" if ALL file all uploaded
    Dim promise As BANanoPromise
    ' the results from the promise
    Dim Result As Map
    Dim Error As String
                     
    ' call the UploadAll method 
    promise.CallSub(Me, "UploadAllFiles"Array(UploadedFiles))
             
    ' when it is done, we can use whatever the UploadAll has returned in its BANano.ReturnThen call 
    ' we use the ThenWait here because we use ...Wait functions or in this case a Sleep
    promise.ThenWait(Result)
           
    Log("Done, going to sleep for 2 seconds just to demonstrate ThenWait()...")
           Sleep(
    2000)
           
    Log("Printing result after 2 seconds")
           
    ' let's show all our urls
           For i = 0 To Result.Size - 1
               
    Log(Result.GetKeyAt(i) & "=" & Result.GetValueAt(i))
           
    Next 
    promise.Then(
    Null)
           
    ' now how about next we make a HTTP request after we got all files             
           DoHTTP("assets/product.json")
    promise.Else(Error)
           
    Log("Error: " & Error)     
    promise.End
    Such a chained promise.Then() can be a promise in itself:
    Code:
    public Sub DoHTTP(Url As StringAs String 'ignore
       ' again we make a new promise
       Dim promise As BANanoPromise
       
    ' some vars to hold our results
       Dim Error As String
       
    Dim json As String
     
       
    ' call the http request
       promise.CallSub(Me, "DoHTTPForUrl"Array(Url))
     
       promise.Then(json)
           
    '  we got it!
           Dim jsonElem As BANanoElement = BANano.GetElement("#json")
           jsonElem.SetText(json)
       promise.Else(Error)
           
    ' whoops, something happened...
           Dim jsonElem As BANanoElement = BANano.GetElement("#json")
           jsonElem.SetText(Error)
       promise.end 
    End Sub
    The demo has documented almost every line, so check it out. What it does:

    1. Allows the user to upload some files

    2. When all downloads are finished, make a http request to download some json

    Note: for the full effect of the demo, use a real Web server (or use the Chrome Web server plugin). If you just open the html file from disk, you'll get something like this:

    [​IMG]

    In case it runs on a Web server, the json is returned:

    [​IMG]

    Alwaysbusy
     
    Last edited: Feb 8, 2019
  2. Harris

    Harris Well-Known Member Licensed User

    ImpressionableOfficialJackal-size_restricted.gif

    You're a very bad man, Jerry....:)

    The recommended way, if this works in BANano?

    Code:
    For Each k As String In Result.Keys

       
    Log"Key: "&k&"   - Value: "&Result.Get(k) )

    Next
    I am very guilty of this as well, but am revising all A and i code... (not much concerned in J and ABM - but I should be).
    Forgive me - couldn't resist.
     
    B4JExplorer and alwaysbusy like this.
  3. alwaysbusy

    alwaysbusy Expert Licensed User

    :)@Harris should work indeed in BANano and would be the recommended way
     
    B4JExplorer and Harris like this.
Loading...
  1. This site uses cookies to help personalise content, tailor your experience and to keep you logged in if you register.
    By continuing to use this site, you are consenting to our use of cookies.
    Dismiss Notice