1

在观看Douglas Crokfrod 关于 monads 和 promises 的演讲时,我对 52:40 提出的一个问题感兴趣。如何使用 Monads 实现看门狗计时器,以便在调用失败函数之前,可以保持承诺或仅在未决状态中存在一段可定义的时间长度。这种模式是否有一个普遍接受的名称?

4

2 回答 2

1

不是,杰森。查看 Crockford 在 GitHub 上的实现,它没有适合该行为的钩子。

也就是说,在典型的 Promise 范式中,有比 Crockford 代码授予的选项更多的选项。

查看 AJAX 库。尽管很多人不知道,但很多 AJAX 库(包括 jQuery)都会返回 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();

我认为,类似的东西应该适用于那里给出的东西。

就个人而言,在看过演讲并阅读了他的实现之后,我认为我更喜欢承诺保留他们的线性队列功能(donefailsuccess/failready/fail或其他),但我见过的大多数库都制作了时间队列(when,,next等)与诺言分开。

所以这里有两个相互竞争的队列,真的。一个订阅事件的地方(比如.addEventListener:当动作发生时,所有的监听器同时被调用),一个订阅下一个结果的最终返回(比如收听正在订阅的东西)一个事件列表器)。

在 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");
于 2013-01-18T21:57:47.890 回答
0

我一直在玩 jQuery 的 Deferred 方法(虽然我找不到语句,但我认为它是单子的),看起来这会起作用(演示)(这看起来太容易了)

function watchdog(promise, time) {
    setTimeout(function() {
        promise.abort();
    }, time);
};

使用JSFiddle中的Ajax 测试挂钩的示例:

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
于 2013-01-18T21:58:37.463 回答