设置 bluebird.js 承诺分辨率的最小延迟 [英] Set minimum delay on bluebird.js promise resolution

查看:8
本文介绍了设置 bluebird.js 承诺分辨率的最小延迟的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想保证 bluebird.js 承诺的解决的最小延迟.

I want to guarantee a minimum delay on the resolution of a bluebird.js promise.

举个例子,假设我正在发出一个包含在 Promise 中的请求.我想要的行为是,如果请求时间少于5秒,我想人为地将promise解析的延迟增加到5秒.如果请求需要超过 5 秒,我不希望添加人为延迟 - 所以它比向每个请求添加静态延迟要复杂一些.所有这一切都应该对 Promise 的使用者完全隐藏 - 他们应该只看到 5 秒或更长时间内解决的承诺.

As an example, let's say I'm making a request wrapped in a promise. The behaviour I want is that if the request takes less than 5 seconds, I want to artificially increase the delay of the promise resolution to 5 seconds. If the request were to take more than 5 seconds, I'd want no artificial delay added - so it's a little more complicated than just adding a static delay to every request. All of this should be completely hidden from the consumer of the promise - they should just see the promise being resolved in 5 seconds, or more.

为了演示,我有一个简单的模拟实现示例,它硬编码模拟请求延迟为 3 秒.

To demonstrate, I've got a simple mock implementation example which hardcodes the mocked request latency at 3 seconds.

我的第一次尝试是这样的 - 使用 setTimeout 来确保在 5 秒过去之前不会调用解析回调.

My first try went something like this - using a setTimeout to ensure the resolve callback isn't called before 5 seconds have passed.

在这里小提琴

function getTimestamp() {
  return new Date().getTime();   
}

function makeCallWith3SecondLatency(cb) {
  console.log('mocking a call with 3 second latency...');
  var mockResult = 'the result';
  setTimeout(function() { cb(mockResult); }, 3000);
}

function doSomethingAsync(minDelay) {
  return new Promise(function(resolve) {
    var calledAt = getTimestamp();
    makeCallWith3SecondLatency(function(arg) {
      var actualDelay = getTimestamp() - calledAt;
      if(actualDelay < minDelay) {
        var artificialDelay = minDelay - actualDelay;
        console.log('artificially delay another ' + artificialDelay + ' millis');
        setTimeout(function() { resolve(arg); }, artificialDelay);
      } else {
        resolve(arg);
      }
    });
  });
}

function printResult(result) {
  console.log('result: ' + result)   
}

var minDelay = 5000;
doSomethingAsync(minDelay).then(printResult);

很多样板.

然后我通过这个答案发现我可以使用 Promise.join 函数加入承诺用最少 5 秒延迟的 Promise.delay 包装请求以实现相同的目标:

I then discovered through this answer that I could use the Promise.join function to join the promise wrapping the request with a Promise.delay of the minimum 5 second delay to achieve the same thing:

在这里小提琴

function makeCallWith3SecondLatency(cb) {
  console.log('mocking a call with 3 second latency...');
  var mockResult = 'the result';
  setTimeout(function() { cb(mockResult); }, 3000);
}

function doSomethingAsync(minDelay) {
  return Promise.join(
                new Promise(function(resolve) { makeCallWith3SecondLatency(resolve); }),
                Promise.delay(minDelay).then(function() { console.log('artificially delaying 5 seconds with Promise.delay') }),
                function(result) { return result; });
}

function printResult(result) {
  console.log('result: ' + result)   
}

var minDelay = 5000;
doSomethingAsync(minDelay).then(printResult);

这更干净,但仍然比我想要的样板多一点 - 我已经挖掘了 bluebird api 参考 并且找不到直接执行此操作的函数.

This is cleaner, but still a little more boilerplate than I'd like - I've dug around the bluebird api reference and can't find a function which does this directly.

我的问题很简单 - 有人可以建议一种比第二个示例更清晰、更具声明性的方法来使用 bluebird 实现这种行为吗?

My question is simple - can anybody suggest a cleaner, more declarative way of achieving this behaviour with bluebird than the second example?

对于 api 确实提供此功能的其他承诺库的任何建议也将不胜感激.

Any suggestions of other promise libraries where the api does offer this would also be appreciated.

推荐答案

我相信你只需要Promise.delay(value).return(promise):

您可以将其包装在实用函数中:

You can wrap it in a utility function:

function stallPromise(promise, delay) {
    return Promise.delay(delay).return(promise);
}

function doSomethingAsync(minDelay) {
    var p = new Promise(makeCallWith3SecondLatency); 

    return stallPromise(p, minDelay);
}

var minDelay = 5000;
doSomethingAsync(minDelay).then(printResult);

http://jsfiddle.net/s572rg7y/1/

注意,关于这一点的一件事是,如果承诺拒绝,延迟的承诺在五秒钟过去之前不会拒绝.这可能是所需的行为(正如@Benjamin Gruenbaum 在评论中指出的那样),但如果您希望它立即拒绝,另外两个选项是:

Note that one thing about this is that if the promise rejects, the delayed promise will not reject until the five seconds have elapsed. This may be the desired behavior (as @Benjamin Gruenbaum points out in the comments), but if you would prefer for it to reject immediately, two other options are:

使用Promise.join:

function stallPromise(promise, delay) {
    // if you're using underscore/lodash, you can use _.identity for this
    function identity(val) { return val; }

    return Promise.join(promise, Promise.delay(delay), identity);
}

或者@Benjamin Gruenbaum 使用 Promise.all 的方法:

Or @Benjamin Gruenbaum's approach with Promise.all:

function minDelay(promise, delay) {
    Promise.all([promise, Promise.delay(delay)]).get(0);
}

这篇关于设置 bluebird.js 承诺分辨率的最小延迟的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆