对尚未建立的承诺的承诺
…很容易通过将
then调用与创建承诺的回调链接起来来构建,以保证将来可以创建承诺。
如果您承诺一个承诺,则 永远不要 使用延迟模式。
Promise当且仅当您要等待异步且 尚未涉及promise
时,才应使用deferreds或构造函数。在所有其他情况下,您应该撰写多个承诺。
当你说
当API调用排入队列时,将在将来的某个时刻创建对网络请求的承诺
那么您不应该创建一个延后的协议,以便在创建承诺后就可以稍后解决(或者更糟的是,一旦实现承诺,就可以用承诺结果来解决它),而应该在将来的某个时刻获得承诺网络要求将完成。基本上你要写
return waitForEndOfQueue().then(makeNetworkRequest);
当然,我们将需要分别更改队列。
var queue_ready = Promise.resolve(true);function callAPI(params) { var result = queue_ready.then(function(API_available) { return doRealNetRequest(params); }); queue_ready = result.then(function() { return true; }); return result;}这具有额外的好处,您将需要显式处理队列中的错误。在这里,一旦一个请求失败(您可能想要更改它),每个调用都会返回一个被拒绝的承诺-
在您的原始代码中,
queue刚被卡住(您可能没有注意到)。
第二种情况稍微复杂一些,因为它确实涉及到
setTimeout调用。这是一个异步原语,我们需要手动为其构建承诺-
但仅用于超时,而没有其他目的。再次,我们将获得超时的承诺,然后只需将我们的API调用链接到该请求即可获得我们想要返回的承诺。
function TimeoutQueue(timeout) { var data = [], timer = 0; this.promise = new Promise(resolve => { this.renew = () => { clearTimeout(timer); timer = setTimeout(resolve, timeout); }; }).then(() => { this.constructor(timeout); // re-initialise return data; }); this.add = (datum) => { data.push(datum); this.renew(); return this.promise; };}var queue = new TimeoutQueue(10);function callAPI2(data) { return queue.add(data).then(callAPI);}您可以在此处看到:a)如何完全消除抖动的逻辑
callAPI2(可能没有必要,但有一点很重要),以及b)promise构造函数如何仅与超时有关,而没有其他问题。它甚至不需要
resolve像延迟的那样“泄漏”该功能,它唯一可用于外部的就是
renew允许扩展计时器的功能。


![对于未使用递延[anti]模式创建的承诺的承诺 对于未使用递延[anti]模式创建的承诺的承诺](http://www.mshxw.com/aiimages/31/420756.png)
