本机Javascript承诺没有任何超时机制。
有关您的实现的问题可能更适合http://prereview.stackexchange.com,但有几点注意事项:
您没有提供在诺言中实际做任何事情的方法,并且
由于计划了一次计时器,因此不需要
clearTimeout
在setTimeout
回调中进行setTimeout
。由于承诺一旦被解决/被拒绝,就无法被解决/被拒绝,因此您不需要进行检查。
所以也许遵循以下思路:
function myPromise(ms, callback) { return new Promise(function(resolve, reject) { // Set up the real work callback(resolve, reject); // Set up the timeout setTimeout(function() { reject('Promise timed out after ' + ms + ' ms'); }, ms); });}像这样使用:
myPromise(2000, function(resolve, reject) { // Real work is here});(或者您 可能 希望它稍微复杂一些,请参见下面的更新。)
我会稍微担心以下事实,即语义会稍有不同(no
new,而您确实使用
new了
Promise构造函数),因此可以进行调整。
当然,另一个问题是,在大多数情况下,您不想构建新的Promise,因此无法使用以上内容。大多数时候,您已经有一个承诺(上一次
then通话的结果,等等)。但是,对于真正要构建新承诺的情况,可以使用上述类似方法。
您可以
new通过子类化处理
Promise:
class MyPromise extends Promise { constructor(ms, callback) { // We need to support being called with no milliseconds // value, because the various Promise methods (`then` and // such) correctly call the subclass constructor when // building the new promises they return. // This pre to do it is ugly, could use some love, but it // gives you the idea. let haveTimeout = typeof ms === "number" && typeof callback === "function"; let init = haveTimeout ? callback : ms; super((resolve, reject) => { init(resolve, reject); if (haveTimeout) { setTimeout(() => { reject("Timed out"); }, ms); } }); }}用法:
let p = new MyPromise(300, function(resolve, reject) { // ...});p.then(result => {}).catch(error => {});现场示例:
// Uses var instead of let and non-arrow functions to try to be// compatible with browsers that aren't quite fully ES6 yet, but// do have promises...(function() { "use strict"; class MyPromise extends Promise { constructor(ms, callback) { var haveTimeout = typeof ms === "number" && typeof callback === "function"; var init = haveTimeout ? callback : ms; super(function(resolve, reject) { init(resolve, reject); if (haveTimeout) { setTimeout(function() { reject("Timed out"); }, ms); } }); } } var p = new MyPromise(100, function(resolve, reject) { // We never resolve/reject, so we test the timeout }); p.then(function(result) { snippet.log("Resolved: " + result); }).catch(function(reject) { snippet.log("Rejected: " + reject); });})();<!-- script provides the `snippet` object, see http://meta.stackexchange.com/a/242144/134069 --><script src="http://tjcrowder.github.io/simple-snippets-console/snippet.js"></script>reject计时器到期时,即使回调调用
resolve或
reject第一次调用,这两者都将调用。这很好,承诺的结算状态不能一旦它的设置改变,该规范定义来电
resolve或
reject上一个已经解决的不产生错误的DO-
空话的承诺。
但是,如果麻烦您了,您可以把
resolve和包装起来
reject。这里的
myPromise这样做的方式:
function myPromise(ms, callback) { return new Promise(function(resolve, reject) { // Set up the timeout let timer = setTimeout(function() { reject('Promise timed out after ' + ms + ' ms'); }, ms); let cancelTimer = _ => { if (timer) { clearTimeout(timer); timer = 0; } }; // Set up the real work callback( value => { cancelTimer(); resolve(value); }, error => { cancelTimer(); reject(error); } ); });}您可以旋转约18种不同的方式,但是基本概念是,
resolve并且
reject我们通过收到的promise执行程序是清除计时器的包装器。
但是 ,这会创建不需要的函数和额外的函数调用。规范明确了已解决诺言时的解决功能。他们很早就退出了。



