我认为我终于在大多数情况下绕过了javascript / ES6 Promises。这并不容易!但是有些东西让我对这个设计感到困惑。
为什么Promise构造函数会进行回调?鉴于立即调用回调,调用者不能只执行该代码,从而避免一个不必要的心灵弯曲,不要打电话给我,我会打电话给你&# 34;
这就是我所认为的Promise使用的典型示例,复制自Jake Archibald的Javascript Promises教程http://www.html5rocks.com/en/tutorials/es6/promises/#toc-promisifying-xmlhttprequest,并删除了评论。
它是XMLHttpRequest GET请求的基于Promise的包装器:
function get(url) {
return new Promise(function(resolve, reject) {
var req = new XMLHttpRequest();
req.open('GET', url);
req.onload = function() {
if (req.status == 200) {
resolve(req.response);
}
else {
reject(Error(req.statusText));
}
};
req.onerror = function() {
reject(Error("Network Error"));
};
req.send();
});
}
对我来说,上面的代码会更容易理解,如果它被重写如下,使用我想象的一种非常不同的承诺,有一个无参数构造函数和解析/拒绝方法:
function get(url) {
var promise = new MyEasierToUnderstandPromise();
var req = new XMLHttpRequest();
req.open('GET', url);
req.onload = function() {
if (req.status == 200) {
promise.resolve(req.response);
}
else {
promise.reject(Error(req.statusText));
}
};
req.onerror = function() {
promise.reject(Error("Network Error"));
};
req.send();
return promise;
}
MyEasierToUnderstandPromise在Promise方面实施起来并不难。起初我尝试将它变成Promise的实际子类,但由于某种原因,我无法让它工作;所以我把它实现为一个简单的工厂函数,它返回一个带有一些额外函数的普通旧Promise对象 附加行为像成员函数:
function NewMyEasierToUnderstandPromise() {
var resolveVar;
var rejectVar;
var promise = new Promise(function(resolveParam, rejectParam) {
resolveVar = resolveParam;
rejectVar = rejectParam;
});
promise.resolve = resolveVar;
promise.reject = rejectVar;
return promise;
};
那么,为什么承诺不是这样设计的?我想如果是的话,它会帮助我更快地理解Promise--我敢打赌它会把我的学习时间缩短一半。
我知道很多聪明人都参与制作Promise API,每个人似乎都很高兴并为此感到自豪,所以我想知道他们在想什么。
答案 0 :(得分:6)
您的版本不是异常安全的,而Promises / A +是安全的,因为它们被Promise
构造函数捕获。
答案 1 :(得分:5)
Promise旨在用作值。 ES构造函数方法封装了Promise的创建,然后可以像值一样传递它。传递该值时,该值的使用者不需要resolve
和reject
,因此这些函数不应该是公共API的一部分。
(以及有关异常处理和链接的所有内容)
答案 2 :(得分:1)
作为辅助信息,当脚本定义ES6承诺链时,如
var promise = new Promise(executor).then(something).catch(handleError);
将promise变量设置为.catch方法调用返回的promise。实际上,防止整个链或Promise对象被执行程序函数持有的解析/拒绝函数引用进行垃圾收集。如果调用resolve(通常在执行程序返回之后但在让解析/拒绝函数超出范围之前异步),then
监听器"某些东西"调用,使用Promise平台内部执行程序,为then
调用返回的promise保存解析/拒绝函数引用,以防止它及其后续链接的承诺过早被垃圾收集。
在建议的延迟模型下,您无法以这种方式设置承诺链,因为您需要引用链中的第一个承诺才能解析或拒绝它。代码变得更像
var promise = new Promise(); // no executor
promise.then(something).catch(handleError);
initiateOperation( promise);
然后在操作响应代码
中异步promise.resolve(value); // if no error occurred
promise = null; // explicit discard of first promise reference to allow GC?
ES6承诺的一般小规模方法现在开始看起来很有希望(哎哟)。我很同情你学习承诺如何运作的困难 - 一个有趣的旅程!!!