在观看Douglas Crokfrod's talk on monads and promises时,我对52:40时提出的问题很感兴趣。如何使用Monads实现一个看门狗定时器,以便在调用失败函数之前,可以保留一个promise或者只在一段可定义的状态下生存一段时间。这种模式是否具有普遍接受的名称?
答案 0 :(得分:1)
没有,杰森。 看看Crockford在GitHub上的实现,它没有适合这种行为的钩子。
也就是说,在典型的Promise范例中,有比Crockford代码授予的选项更多的选项。
查看AJAX库。尽管很多人不知道它,但很多AJAX库(包括jQuery)都会返回promises。
要在他的代码中执行此操作,您可以根据使用promise参数提交的时间来挂钩一个具有.break
承诺的计时器的子句。
否则,您可以执行以下操作:
var vow = VOW.make(),
last_promise = vow.when()
.when()
.when()
.when() /*...*/;
(function () {
var vow = VOW.make(),
time_over = false,
time_limit = 30 * 1000,
timer_handle,
success = function (value) {
if (time_over) { vow["break"]("Time's up!"); }
else {
clearInterval(timer_handle);
vow.keep(value);
}
};
trailing_promise.when(success, /* fail */);
return vow.promise;
}()).when(/* ... */)
.when()
.when();
我想这样的东西应该适用于那里的东西。
就个人而言,在看完演讲并阅读他的实现后,我认为我更倾向于保留其线性队列功能(done
,fail
或success/fail
或ready/fail
或者其他),但是我见过的大多数库使得时间队列(when
,next
等)与承诺分开。
所以你在这里有两个竞争队列,真的。你订阅一个事件的地方(比如.addEventListener
:当动作发生时,所有的侦听器同时被调用),以及你订阅最终返回下一个结果的一个(比如听订阅eventListner的东西。
在Crockford的最小实现中,它更像是你只能有一个监听器,然后用户收听前一个用户的最后一个用户......
...并且在同一队列中链接多个指令的唯一方法是缓存返回:
var level_0 = VOW.make(),
level_1 = level_0.when(/* ... , ... */),
level_2 = level_1.when(/* ... , ... */);
level_1.when(/* more stuff */);
level_1.when(/* even more */);
level_2.when()
.when()
.when();
// ...eventually.......
level_0.keep("stuff");
答案 1 :(得分:0)
我一直在玩jQuery的Deferred方法(我认为虽然我找不到一个声明,但我觉得它是monadic),看起来这样可行(demo)(这看起来太容易了)< / p>
function watchdog(promise, time) {
setTimeout(function() {
promise.abort();
}, time);
};
使用JSFiddle中的Ajax test hooks的一个例子:
console.log("Waiting 2,000ms for something we think will take 3,000ms to return");
watchdog(
$.post('/echo/html/', { delay: 3 })
.done(function() {console.log("Got It!");})
.fail(function() {console.log('took too long (but I knew that)!');})
.always(function() {console.log('Cleaning up no matter what');})
, 2000);
console.log("Waiting 3,000ms for something we think will take 2,000ms to return");
watchdog(
$.post('/echo/html/', { delay: 2 })
.done(function() {console.log("Got It (but I knew that)!");})
.fail(function() {console.log('took too long!');})
.always(function() {console.log('Cleaning up no matter what');})
, 3000);
这是生成的日志:
Waiting 2,000ms for something we think will take 3,000ms to return
Waiting 3,000ms for something we think will take 2,000ms to return
took too long (but I knew that)!
Cleaning up no matter what
Got It (but I knew that)!
Cleaning up no matter what