Promise.defer() 浏览器支持

21

我正在寻找一种创建延迟对象的方法,该对象将在当前范围之外解决。我喜欢延迟对象,正如我在Chrome 38中看到的Promise.defer()返回延迟对象。

但是在最新的Firefox 34中,Promise.defer是未定义的,同样在Safari 8.0中也是如此。

因此,现在我无法在所有地方使用Promise.defer。未来会怎么样呢?它会被其他浏览器实现,还是会被删除作为不推荐使用的内容?


如果你真的想要,你可以使用 Promise 创建自定义延迟对象。 - dfsq
计划从Chrome和chain中移除。 - Benjamin Gruenbaum
1
Promise.defer()在我的Google Chrome浏览器中已经停止工作。(版本52.0.2743.82) - Andrew Shepherd
2个回答

36

虽然我怀疑这不是一个好主意,但从技术上讲,您可以基于Promises实现自定义延迟对象。例如:

function defer() {
    var deferred = {};
    var promise = new Promise(function(resolve, reject) {
        deferred.resolve = resolve;
        deferred.reject  = reject;
    });
    deferred.promise = promise;
    return deferred;
}

var deferred = defer();

deferred.promise.then(function(data) {
    document.body.innerHTML += '<p>Resolved: ' + data + '</p>';
});

document.body.innerHTML = '<p>Deferred created.</p>';

setTimeout(function() {
    deferred.resolve(123);
}, 2000);


1
这被认为是 Promise 反模式,因为它不允许正确传播错误。 - Alnitak
4
@Alnitak,我知道这一点,那就是为什么我说这不是一个好主意的原因。我只是展示了实现延迟对象在技术上是可行的。 - dfsq
@Alnitak 这与错误传播无关 - 你误将延迟反模式与使用延迟构造 Promise 的情况混淆了。 - Benjamin Gruenbaum
1
@dfsq 我点赞你的解决方案,因为它很实用,而 Alexander O'Mara 提供的解决方案也是正确的。我不确定我还能在这里添加什么了。 - Benjamin Gruenbaum
对于未来思考这个问题的读者。提到的 Promise 反模式与未捕获的异常有关。当启动回调函数抛出异常并且应该进入拒绝处理程序时,它不会进入。更多信息请参见 http://bytearcher.com/articles/pitfalls-of-promisifying-by-band/。 - pspi
显示剩余7条评论

28
根据MDN上的Deferred文章.defer方法已经过时。 如果您查看这个错误问题,它说Promise.defer是非标准的,因此不太可能返回。

从Gecko 30开始,该对象已被弃用,不应再使用。改用new Promise()构造函数。

他们提供了一个示例,说明如何重写Promise.defer代码,改为使用new Promise

Promise.defer

var deferred = Promise.defer();
doSomething(function cb(good) {
    if (good)
        deferred.resolve();
    else
        deferred.reject();
});
return deferred.promise;

新的 Promise

return new Promise(function(resolve, reject) {
    doSomething(function cb(good) {
        if (good)
            resolve();
        else
            reject();
    });
});

新格式有几个优点,包括更简洁的代码和改进的throw安全性(如果promise init函数中的代码同步抛出异常,promise将会被拒绝)。


16
值得一提的是,它被删除的原因——与deferred相比,promise构造函数是throw safe的。如果你在promise构造函数的作用域中抛出异常,它会自动将其转换为一个拒绝(rejection)。 - Benjamin Gruenbaum
@BenjaminGruenbaum,谢谢,这正是我想要的。 - just-boris
2
更加完整的解释:defer().promise和Promise之间的区别 - Bergi
21
然而,在构造函数之外,解决或拒绝一个承诺(deferred)的能力将会丧失。 - Michahell
2
那么当 Promise 需要在构造函数之外被解决/拒绝时,我们现在该怎么办?dfsq 的答案是什么? - Greendrake
http://bluebirdjs.com/docs/api/deferred-migration.html - danday74

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接