diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index a4f85ea2a..36a9a4254 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -29,24 +29,6 @@ jobs:
         toolchain: ${{ matrix.rust }}
         override: true
 
-    - name: Cache cargo registry
-      uses: actions/cache@v2
-      with:
-        path: ~/.cargo/registry
-        key: ${{ matrix.os }}-${{ matrix.rust }}-cargo-registry-${{ hashFiles('**/Cargo.toml') }}
-
-    - name: Cache cargo index
-      uses: actions/cache@v2
-      with:
-        path: ~/.cargo/git
-        key: ${{ matrix.os }}-${{ matrix.rust }}-cargo-index-${{ hashFiles('**/Cargo.toml') }}
-
-    - name: Cache cargo build
-      uses: actions/cache@v2
-      with:
-        path: target
-        key: ${{ matrix.os }}-${{ matrix.rust }}-cargo-build-target-${{ hashFiles('**/Cargo.toml') }}
-
     - name: check
       uses: actions-rs/cargo@v1
       with:
@@ -160,6 +142,41 @@ jobs:
     - name: test
       run: cross test --all --features unstable --target ${{ matrix.target }}
 
+  check_wasm:
+    name: Check wasm targets
+    runs-on: ubuntu-latest
+    strategy:
+      matrix:
+        rust: [nightly, beta, stable]
+
+    steps:
+    - uses: actions/checkout@master
+
+    - name: Install rust with wasm32-unknown-unknown
+      uses: actions-rs/toolchain@v1
+      with:
+        toolchain: ${{ matrix.rust }}
+        target: wasm32-unknown-unknown
+        override: true
+
+    - name: Cache cargo registry
+      uses: actions/cache@v2
+      with:
+        path: ~/.cargo/registry
+        key: wasm32-${{ matrix.rust }}-cargo-registry-${{ hashFiles('**/Cargo.toml') }}
+
+    - name: check
+      uses: actions-rs/cargo@v1
+      with:
+        command: check
+        args: --target wasm32-unknown-unknown 
+
+    - name: check unstable
+      uses: actions-rs/cargo@v1
+      with:
+        command: check
+        args: --target wasm32-unknown-unknown --tests --all --features unstable
+        
   check_fmt_and_docs:
     name: Checking fmt and docs
     runs-on: ubuntu-latest
diff --git a/Cargo.toml b/Cargo.toml
index 0c18ff457..6f6cfe4bd 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -33,11 +33,12 @@ default = [
   "log",
   "num_cpus",
   "pin-project-lite",
+  "gloo-timers",
 ]
 docs = ["attributes", "unstable", "default"]
 unstable = [
   "std",
-  "futures-timer",
+  "async-io"
 ]
 attributes = ["async-attributes"]
 std = [
@@ -74,7 +75,6 @@ once_cell = { version = "1.3.1", optional = true }
 pin-project-lite = { version = "0.1.4", optional = true }
 pin-utils = { version = "0.1.0-alpha.4", optional = true }
 slab = { version = "0.4.2", optional = true }
-futures-timer = { version = "3.0.2", optional = true }
 
 # Devdepencency, but they are not allowed to be optional :/
 surf = { version = "1.0.3", optional = true }
@@ -86,7 +86,7 @@ blocking = { version = "1.0.0", optional = true }
 futures-lite = { version = "1.0.0", optional = true }
 
 [target.'cfg(target_arch = "wasm32")'.dependencies]
-futures-timer = { version = "3.0.2", optional = true, features = ["wasm-bindgen"] }
+gloo-timers = { version = "0.2.1", features = ["futures"], optional = true }
 wasm-bindgen-futures = { version = "0.4.10", optional = true }
 futures-channel = { version = "0.3.4", optional = true }
 
diff --git a/src/task/builder.rs b/src/task/builder.rs
index d3a353691..391201d84 100644
--- a/src/task/builder.rs
+++ b/src/task/builder.rs
@@ -1,4 +1,3 @@
-use std::cell::Cell;
 use std::future::Future;
 use std::pin::Pin;
 use std::sync::Arc;
@@ -7,7 +6,7 @@ use std::task::{Context, Poll};
 use pin_project_lite::pin_project;
 
 use crate::io;
-use crate::task::{self, JoinHandle, Task, TaskLocalsWrapper};
+use crate::task::{JoinHandle, Task, TaskLocalsWrapper};
 
 /// Task builder that configures the settings of a new task.
 #[derive(Debug, Default)]
@@ -61,7 +60,7 @@ impl Builder {
         });
 
         let task = wrapped.tag.task().clone();
-        let handle = task::executor::spawn(wrapped);
+        let handle = crate::task::executor::spawn(wrapped);
 
         Ok(JoinHandle::new(handle, task))
     }
@@ -81,7 +80,7 @@ impl Builder {
         });
 
         let task = wrapped.tag.task().clone();
-        let handle = task::executor::local(wrapped);
+        let handle = crate::task::executor::local(wrapped);
 
         Ok(JoinHandle::new(handle, task))
     }
@@ -143,6 +142,8 @@ impl Builder {
     where
         F: Future<Output = T>,
     {
+        use std::cell::Cell;
+
         let wrapped = self.build(future);
 
         // Log this `block_on` operation.
@@ -167,7 +168,7 @@ impl Builder {
                 TaskLocalsWrapper::set_current(&wrapped.tag, || {
                     let res = if should_run {
                         // The first call should run the executor
-                        task::executor::run(wrapped)
+                        crate::task::executor::run(wrapped)
                     } else {
                         futures_lite::future::block_on(wrapped)
                     };
diff --git a/src/task/join_handle.rs b/src/task/join_handle.rs
index 9189ea576..25ca79dad 100644
--- a/src/task/join_handle.rs
+++ b/src/task/join_handle.rs
@@ -78,7 +78,17 @@ impl<T> Drop for JoinHandle<T> {
 impl<T> Future for JoinHandle<T> {
     type Output = T;
 
+    #[cfg(not(target_os = "unknown"))]
     fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
         Pin::new(&mut self.handle.as_mut().unwrap()).poll(cx)
     }
+
+    #[cfg(target_arch = "wasm32")]
+    fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
+        match Pin::new(&mut self.handle.as_mut().unwrap()).poll(cx) {
+            Poll::Ready(Ok(t)) => Poll::Ready(t),
+            Poll::Ready(Err(_)) => unreachable!("channel must not be canceled"),
+            Poll::Pending => Poll::Pending,
+        }
+    }
 }
diff --git a/src/utils.rs b/src/utils.rs
index 528a7074e..d80524446 100644
--- a/src/utils.rs
+++ b/src/utils.rs
@@ -59,7 +59,10 @@ pub(crate) trait Context {
     fn context(self, message: impl Fn() -> String) -> Self;
 }
 
-#[cfg(all(not(target_os = "unknown"), feature = "default"))]
+#[cfg(all(
+    not(target_os = "unknown"),
+    any(feature = "default", feature = "unstable")
+))]
 mod timer {
     pub type Timer = async_io::Timer;
 }
@@ -69,20 +72,19 @@ pub(crate) fn timer_after(dur: std::time::Duration) -> timer::Timer {
     Timer::after(dur)
 }
 
-#[cfg(any(
-    all(target_arch = "wasm32", feature = "default"),
-    all(feature = "unstable", not(feature = "default"))
-))]
+#[cfg(any(all(target_arch = "wasm32", feature = "default"),))]
 mod timer {
     use std::pin::Pin;
     use std::task::Poll;
 
+    use gloo_timers::future::TimeoutFuture;
+
     #[derive(Debug)]
-    pub(crate) struct Timer(futures_timer::Delay);
+    pub(crate) struct Timer(TimeoutFuture);
 
     impl Timer {
         pub(crate) fn after(dur: std::time::Duration) -> Self {
-            Timer(futures_timer::Delay::new(dur))
+            Timer(TimeoutFuture::new(dur.as_millis() as u32))
         }
     }
 
diff --git a/tests/collect.rs b/tests/collect.rs
index d24484f4e..7ab80ccc9 100644
--- a/tests/collect.rs
+++ b/tests/collect.rs
@@ -1,6 +1,6 @@
 #[cfg(feature = "unstable")]
 #[test]
-fn test_send() -> async_std::io::Result<()> {
+fn test_send() {
     use async_std::prelude::*;
     use async_std::{stream, task};
 
@@ -14,7 +14,5 @@ fn test_send() -> async_std::io::Result<()> {
 
         // This line triggers a compilation error
         test_send_trait(&fut);
-
-        Ok(())
-    })
+    });
 }