Using promises with Transcrypt

2019-05-20 05:10发布

问题:

I'm having great fun with Transcrypt, a fantastic Python 3 to Javascript compiler available as a python module. Most of my code is synchronous, but i've had no problem doing things with setTimeout and XHR requests. Now i've started using PouchDB for local persistence and am trying to find a pretty way to handle promises. At the moment, I am doing this to write to a pouchdb instance:

def db_put():

    def put_success(doc):
        print("Put a record in the db. Id: ", doc.id, "rev: ", doc.rev)

    def put_failure(error):
        print('Failed to put a record in the db. Error: ', error)

    strHello = {'_id': "1", 'title': 'hello db'}
    db.put(strHello) \
    .then(put_success) \
    .catch(put_failure)

db = PouchDB('test_db')
document.getElementById("db_put").addEventListener("click", db_put)

This works fine, but I am curious to know a few things about promises being transcrypted from python to Javascript (this may save me from madness):

  • Are there more preferable 'pythonic' ways to handle this?
  • Can one make use of ES7's async / await through Transcrypt? Since Transcrypt allows Javascript functions to be accessed directly from within the python code, i thought there might be some trick here that i'm not getting..

Thanks!

回答1:

About the promises

The way you dealt with promises looks pythonic enough to me.

In case you get tired of the line continuations where 'fluent' notation (call chaining) is involved, there's an alternative to using \. This alternative is used e.g. in the d3js_demo that comes with Transcrypt, in the following fragment:

self.svg = d3.select('body'
).append('svg'
).attr('width', self.width
).attr('height', self.height
).on('mousemove', self.mousemove
).on('mousedown', self.mousedown)

Since many .then's can be chained as well, one could write:

db.put(strHello
).then(put_success
).then(put_success_2
).then(put_success_3
... etc.
).catch(put_failure)

After some getting used to, this will immediately make clear that call chaining is involved. But it is only a matter of formatting.

about async/await

They aren't yet supported, but the plan is they will be soon after JS officially has them (JS7, I hope). For now you can use __pragma__ ('js', '{}', '''<any javascript code>''') as a workaround.



回答2:

Async/await is supported some time now. You can use it to deal with Promises. For example:

Enable JQuery usage:

__pragma__ ('alias', 'S', '$')

Define a function which returns a Promise, in this case an Ajax call:

def read(url: str) -> 'Promise':
    deferred = S.Deferred()
    S.ajax({'type': "POST", 'url': url, 'data': { },
        'success': lambda d: deferred.resolve(d),
        'error': lambda e: deferred.reject(e)
    })
    return deferred.promise()

Use the asynchronous code as if it were synchronous:

async def readALot():
    try:
        result1 = await read("url_1")
        result2 = await read("url_2")
    except Exception:
        console.warn("Reading a lot failed")

Happy usage of python in the browser



标签: transcrypt