Promise implementation in Python

Recently I made an basic port of the JavaScript Promise construct to Python. Here's the basic code:

class Promise:
def __init__(self, fn):
self.value = None
self.errors = []
self._state = "unfullfilled"

def resolve(val):
if self._state == "settled":
return
self.value = val
self._state = "settled"
def reject(err):
if self._state == "settled":
return
self.errors.append(err)
self._state = "settled"
fn(resolve, reject)

def catch(self, fn):
if self.errors:
for i in self.errors:
fn(i)
self.errors.remove(i)
return self

def then(self, fn):
if not self.errors:
fn(self.value)
return self

@staticmethod
def resolve(val):
def g(resolve, reject):
resolve(val)
return Promise(g)

@staticmethod
def reject(val):
def g(resolve, reject):
reject(val)
return Promise(g)


What could I improve in this code? Besides that, are there any bugs in this code?

• Welcome to codereview. Have you checked promise module? – Grajdeanu Alex. Mar 5 '18 at 9:13
• This code is for personal use. I was just checking if it is okay to write code in this manner. – Vikram Durai Mar 5 '18 at 13:06

Thank you for showing your code. You really should show us how to use it, by including unit tests, a reference URL, or with comments. At a minimum the class needs a docstring.

self._state = "unfullfilled"


Typo. Consider using enum.Enum instead of str.

self.value = None


This appears to be just wrong. (Hard to tell, since no docstring describes what valid callers may do.) A fn could choose to return None, yes? The usual approach for such a sentinel is to invoke object() to create a private object, essentially an allocated memory location that other code doesn't know about. Then test equality against that. If, on the other hand, you want your API to prohibit passing None, then you'll want to add some checks for that.

self.errors.remove(i)


That's an odd way to phrase it. The usual idiom for the loop you wrote would be to .pop() the initial element. Consider switching from list to deque if lots of errors might accumulate.