this needs `return d.promise` otherwise the next `then` won't wait for reject/resolve