使用Promises时,为什么不能在代码库的其他地方定义resolve
和reject
的触发器?
我不明白为什么resolve
和reject
逻辑应该在声明promise的位置进行本地化。这是疏忽,还是强制要求executor
参数?
我认为执行函数应该是可选的,并且它的存在应该确定promise是否封装了解决方案。如果没有这样的要求,承诺将更加可扩展,因为您不必立即启动异步。承诺也应该是可以重置的。它是1个开关,1或0,resolve()
或reject()
。可附加多个并行和顺序结果:promise.then(parallel1)
和promise.then(parallel2)
以及promise.then(seq1).then(seq2)
但参考特权玩家无法解析/拒绝INTO切换
你可以在以后构建一个结果树,但是你不能改变它们,也不能改变根(输入触发器)
老实说,顺序结果的树也应该是可编辑的......假设你想要拼出一个步骤并在你宣布许多承诺链之后做其他事情。重建承诺和每个顺序功能都没有意义,特别是因为你甚至不能拒绝或摧毁承诺...
答案 0 :(得分:12)
这被称为由Domenic创造的the revealing constructor pattern。
基本上,我们的想法是让您访问对象的部分,而该对象尚未完全构建。引用Domenic:
我称之为揭示构造函数模式,因为Promise构造函数正在揭示其内部功能,但仅限于构造相关承诺的代码。解决或拒绝承诺的能力仅在构造代码中显示,并且对于使用承诺的任何人来说都是至关重要的。因此,如果我们将p交给另一个消费者,请说
最初,promises使用延迟对象,这在JavaScript承诺的Twisted promises中也是如此。在Angular的$q
,Q,jQuery和旧版本的旧版本中,这仍然是正确的(但经常被弃用)。蓝鸟。
API类似于:
var d = Deferred();
d.resolve();
d.reject();
d.promise; // the actual promise
它有效,但它有问题。 Deferreds和promise构造函数通常用于将非承诺API转换为promise。 JavaScript中存在一个名为Zalgo的“着名”问题 - 基本上,它意味着API必须是同步的或异步的,但不能同时进行。
事情是 - 通过延迟,可以做类似的事情:
function request(param) {
var d = Deferred();
var options = JSON.parse(param);
d.ajax(function(err, value) {
if(err) d.reject(err);
else d.resolve(value);
});
}
这里有一个隐藏的细微错误 - 如果param
不是一个有效的JSON,这个函数会同步抛出,这意味着我必须在{{1}中包装每个promise返回函数并且} catch (e) {
可以捕获所有错误。
promise构造函数捕获此类异常并将其转换为拒绝,这意味着您永远不必担心同步异常与使用promises的异步异常。 (它通过在下一个勾号中始终执行.catch(e =>
回调来保护你的另一方。)
此外,它还需要一个额外的类型,每个开发人员必须了解promise构造函数不适合的地方。
答案 1 :(得分:4)
仅供参考,如果您仍然希望使用延迟接口而不是Promise执行器接口,尽管有很好的理由反对延迟接口,您可以轻松编码一次,然后在任何地方使用它(我个人认为这是个坏主意)以这种方式编码,但是你对这个主题的问题表明你的思维方式不同,所以这里是:)
function Deferred() {
var self = this;
var p = this.promise = new Promise(function(resolve, reject) {
self.resolve = resolve;
self.reject = reject;
});
this.then = this.promise.then.bind(p);
this.catch = this.promise.catch.bind(p);
}
现在,您可以使用您似乎要求的界面:
var d = new Deferred();
d.resolve();
d.reject();
d.promise; // the actual promise
d.then(...) // can use .then() on either the Deferred or the Promise
d.promise.then(...)
这是一个稍微紧凑的ES6版本:
function Deferred() {
let p = this.promise = new Promise((resolve, reject) => {
this.resolve = resolve;
this.reject = reject;
});
this.then = this.promise.then.bind(p);
this.catch = this.promise.catch.bind(p);
}
或者,您可以使用此Deferred()
构造函数执行您在问题中要求的内容:
var request = new Deferred();
request.resolve();
request.then(handleSuccess, handleError);
但是,它有本杰明指出的缺点,并不被认为是编码承诺的最佳方式。
显示类似的内容here on MDN。