diff --git a/param/_async.py b/param/_async.py
new file mode 100644
index 000000000..144c50782
--- /dev/null
+++ b/param/_async.py
@@ -0,0 +1,29 @@
+"""
+Module that implements asyncio.coroutine function wrappers to be used
+by param internal callbacks. These are defined in a separate file due
+to py2 incompatibility with both `async/await` and `yield from` syntax.
+"""
+
+import asyncio
+
+def generate_depends(func):
+    @asyncio.coroutine
+    def _depends(*args, **kw):
+        yield from func(*args, **kw) # noqa: E999
+    return _depends
+
+def generate_caller(function, what='value', changed=None, callback=None, skip_event=None):
+    @asyncio.coroutine
+    def caller(*events):
+        if callback: callback(*events)
+        if not skip_event or not skip_event(*events, what=what, changed=changed):
+            yield from function() # noqa: E999
+    return caller
+
+def generate_callback(func, dependencies, kw):
+    @asyncio.coroutine
+    def cb(*events):
+        args = (getattr(dep.owner, dep.name) for dep in dependencies)
+        dep_kwargs = {n: getattr(dep.owner, dep.name) for n, dep in kw.items()}
+        yield from func(*args, **dep_kwargs) # noqa: E999
+    return cb
diff --git a/param/parameterized.py b/param/parameterized.py
index fff302156..86f88281a 100644
--- a/param/parameterized.py
+++ b/param/parameterized.py
@@ -390,10 +390,8 @@ def depends(func, *dependencies, **kw):
     on_init = kw.pop("on_init", False)
 
     if iscoroutinefunction(func):
-        import asyncio
-        @asyncio.coroutine
-        def _depends(*args, **kw):
-            yield from func(*args, **kw)
+        from ._async import generate_depends
+        _depends = generate_depends(func)
     else:
         @wraps(func)
         def _depends(*args, **kw):
@@ -430,12 +428,8 @@ def _depends(*args, **kw):
 
     if not string_specs and watch: # string_specs case handled elsewhere (later), in Parameterized.__init__
         if iscoroutinefunction(func):
-            import asyncio
-            @asyncio.coroutine
-            def cb(*events):
-                args = (getattr(dep.owner, dep.name) for dep in dependencies)
-                dep_kwargs = {n: getattr(dep.owner, dep.name) for n, dep in kw.items()}
-                yield from func(*args, **dep_kwargs)
+            from ._async import generate_callback
+            cb = generate_callback(func, dependencies, kw)
         else:
             def cb(*events):
                 args = (getattr(dep.owner, dep.name) for dep in dependencies)
@@ -657,12 +651,8 @@ def _m_caller(self, method_name, what='value', changed=None, callback=None):
     """
     function = getattr(self, method_name)
     if iscoroutinefunction(function):
-        import asyncio
-        @asyncio.coroutine
-        def caller(*events):
-            if callback: callback(*events)
-            if not _skip_event(*events, what=what, changed=changed):
-                yield from function()
+        from ._async import generate_caller
+        caller = generate_caller(function, what=what, changed=changed, callback=callback, skip_event=_skip_event)
     else:
         def caller(*events):
             if callback: callback(*events)
diff --git a/tests/API1/testparamdepends.py b/tests/API1/testparamdepends.py
index 3128c6b9d..2c5e586ef 100644
--- a/tests/API1/testparamdepends.py
+++ b/tests/API1/testparamdepends.py
@@ -1,15 +1,30 @@
 """
 Unit test for param.depends.
 """
-
-import pytest
+import sys
 
 import param
+import pytest
 
 from param.parameterized import _parse_dependency_spec
 
 from . import API1TestCase
 
+try:
+    import asyncio
+except ImportError:
+    asyncio = None
+
+
+def async_executor(func):
+    # Could be entirely replaced by asyncio.run(func()) in Python >=3.7
+    try:
+        loop = asyncio.get_event_loop()
+    except RuntimeError:
+        loop = asyncio.new_event_loop()
+        asyncio.set_event_loop(loop)
+    loop.run_until_complete(func())
+
 
 class TestDependencyParser(API1TestCase):
 
@@ -638,7 +653,25 @@ def test_param_external_param_instance(self):
         self.assertIs(pinfo.inst, None)
         self.assertEqual(pinfo.name, 'a')
         self.assertEqual(pinfo.what, 'value')
-
+    
+    @pytest.mark.skipif(sys.version_info.major == 2, reason='asyncio only on Python 3')
+    def test_async(self):
+        try:
+            param.parameterized.async_executor = async_executor
+            class P(param.Parameterized):
+                a = param.Parameter()
+                single_count = param.Integer()
+
+                @param.depends('a', watch=True)
+                @asyncio.coroutine
+                def single_parameter(self):
+                    self.single_count += 1
+
+            inst = P()
+            inst.a = 'test'
+            assert inst.single_count == 1
+        finally:
+            param.parameterized.async_executor = None
 
 
 class TestParamDependsFunction(API1TestCase):
@@ -711,6 +744,25 @@ def function(value, c):
         p.b = 3
         self.assertEqual(d, [4, 5])
 
+    @pytest.mark.skipif(sys.version_info.major == 2, reason='asyncio only on Python 3')
+    def test_async(self):
+        try:
+            param.parameterized.async_executor = async_executor
+            p = self.P(a=1)
+
+            d = []
+
+            @param.depends(p.param.a, watch=True)
+            @asyncio.coroutine
+            def function(value):
+                d.append(value)
+
+            p.a = 2
+
+            assert d == [2]
+        finally:
+            param.parameterized.async_executor = None
+
 
 def test_misspelled_parameter_in_depends():
     class Example(param.Parameterized):