Skip to content

Instantly share code, notes, and snippets.

@wware
Created October 1, 2014 21:41
Show Gist options
  • Save wware/56b81be344fce75e1431 to your computer and use it in GitHub Desktop.
Save wware/56b81be344fce75e1431 to your computer and use it in GitHub Desktop.
Can we do a JavaScript-like .then() hack in Python?
# Can we do a JavaScript-like .then() hack in Python?
import threading
import time
class Sleeper(threading.Thread):
def __init__(self):
super(Sleeper, self).__init__()
self.f = None
self.start()
def run(self):
time.sleep(2)
if callable(self.f):
self.f()
def then(self, f):
self.f = f
def move_motor_up(steps):
print 'UP', steps
return Sleeper()
def move_motor_down(steps):
print 'DOWN', steps
return Sleeper()
def up():
move_motor_up(100).then(
lambda: move_motor_down(100).then(up)
)
up()
@wware
Copy link
Author

wware commented Oct 2, 2014

When leaving this infinite loop running, would you end up accumulating a huge collection of un-garbage-collected Sleeper instances? To test that, I put print statements in Sleeper.__init__ and Sleeper.__del__. No more than two of them are ever alive, so this might be a pretty good design pattern.

This came up in the context of sending commands to a widget and getting back asynchronous responses, and there are many different flavors of command/response pairings, and several commands can be in-process at any given moment. So you want some kind of event-handler approach, and borrowing JS's .then() pattern seemed sensible.

To apply this to an embedded control scenario, Sleeper would not inherit from Thread, and the __init__ and run methods would be replaced by something like this.

    def __init__(self, *args):
        widget.sendCommand(args)
        self.f = None

    def onResponseReceived(self):
        # perform sanity checks, raise Exception if not in the expected state
        if callable(self.f):
            self.f()

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment