如何在承诺中包装setTimeout [英] How do you wrap setTimeout in a promise

查看:86
本文介绍了如何在承诺中包装setTimeout的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试为返回promise的对象运行测试套件。我希望将几个动作连在一起,并在它们之间进行短暂的超时。我认为返回承诺的then调用将等待承诺在触发下一个chained然后调用之前完成。

I am trying to run a test suite for an object that returns a promise. I want to chain several actions together with short timeouts between them. I thought that a "then" call which returned a promise would wait for the promise to be fulfilled before firing the next chained then call.

我创建了一个函数

function promiseTimeout (time) {
  return new Promise(function(resolve,reject){
    setTimeout(function(){resolve(time);},time);
  });
};

尝试在承诺中包装setTimeout。

to try and wrap setTimeout in a Promise.

然后在我的测试套件中,我正在调用这样的东西...

Then in my test suite, I am calling something like this ...

    it('should restore state when browser back button is used',function(done){
      r.domOK().then(function(){
        xh.fire('akc-route-change','/user/4/profile/new');
      }).then(promiseTimeout(2000)).then(function(t){
        xu.fire('akc-route-change','/user/6');
      }).then(promiseTimeout(10)).then(function(t){
        expect(xu.params[0]).to.equal(6);
        history.back();
      }).then(promiseTimeout(10)).then(function(){
        expect(xu.params[0]).to.equal(4);
        done();
      });
    });

我可以在第一个 xh.fire上放置一个断点 xu.fire 调用中调用和第二个调用,并且当从第一个断点继续到第二个断点时,预计会有两秒的差距。

I can put a breakpoint on the first xh.fire call and a second one on the xu.fire call and would have expected a two second gap when a continues from the first breakpoint to the second.

而是立即到达第二个断点,此时 t 的值未定义。

Instead it reaches the second breakpoint immediately, and the value of t at that point is undefined.

我做错了什么?

推荐答案

TL; DR - 你是在承诺中正确包装setTimeout,问题是你使用不当

TL;DR - you've wrapped setTimeout in a promise properly, the issue is you are using it improperly

.then(promiseTimeout(2000)).then

不会达到您的预期。 .then的签名是然后(functionResolved,functionRejected)

will not do what you expect. The "signature" for .then is then(functionResolved, functionRejected)


A promise的then方法接受两个参数:

A promise’s then method accepts two arguments:

promise.then(onFulfilled,onRejected)

promise.then(onFulfilled, onRejected)

onFulfilled和onRejected都是可选参数:

Both onFulfilled and onRejected are optional arguments:


  • 如果onFulfilled不是函数,则必须忽略它。

  • 如果onRejected不是函数,必须忽略它。

source: https://promisesaplus.com/#point-21

你没有传递函数然后

考虑你的方式:

Promise.resolve('hello')
.then(promiseTimeout(2000))
.then(console.log.bind(console))

与应如何完成:

Promise.resolve('hello').then(function() { 
    return promiseTimeout(2000)
}).then(console.log.bind(console))

第一个输出'hello'立即

The first outputs 'hello' immediately

第二个输出2000秒后2秒

The second outputs 2000 after 2 seconds

因此,您应该这样做:

it('should restore state when browser back button is used', function(done) {
    r.domOK().then(function() {
        xh.fire('akc-route-change', '/user/4/profile/new');
    }).then(function() {
        return promiseTimeout(2000);
    }).then(function(t) {
        xu.fire('akc-route-change', '/user/6');
    }).then(function() {
        return promiseTimeout(10);
    }).then(function(t) {
        expect(xu.params[0]).to.equal(6);
        history.back();
    }).then(function() {
        return promiseTimeout(10);
    }).then(function() {
        expect(xu.params[0]).to.equal(4);
        done();
    });
});

另外:

it('should restore state when browser back button is used', function(done) {
    r.domOK().then(function() {
        xh.fire('akc-route-change', '/user/4/profile/new');
    }).then(promiseTimeout.bind(null, 2000)
    ).then(function(t) {
        xu.fire('akc-route-change', '/user/6');
    }).then(promiseTimeout.bind(null, 10)
    ).then(function(t) {
        expect(xu.params[0]).to.equal(6);
        history.back();
    }).then(promiseTimeout.bind(null, 10)
    ).then(function() {
        expect(xu.params[0]).to.equal(4);
        done();
    });
});



编辑:2019年3月



March 2019


多年来,情况发生了很大的变化 - 箭头符号使这更加容易

Over the years, things have changed a lot - arrow notation makes this even easier

首先,我要定义promiseTimeout不一样

Firstly, I would define promiseTimeout differently

const promiseTimeout = time => () => new Promise(resolve => setTimeout(resolve, time, time));

上面返回一个函数,可以调用该函数来创建promise delay并解析为时间(延迟时间)。考虑到这一点,我不明白为什么那会非常有用,而不是我:

The above returns a function that can be called to create a "promise delay" and resolves to the time (length of delay). Thinking about this, I can't see why that would be very useful, rather I'd:

const promiseTimeout = time => result => new Promise(resolve => setTimeout(resolve, time, result));

以上将解析前一个承诺的结果(更有用)

The above would resolve to the result of the previous promise (far more useful)

但它是一个返回函数的函数,因此ORIGINAL代码的其余部分可以保持不变。然而,关于原始代码的事情是,不需要在.then链下传递任何值,因此,更简单

But it's a function that returns a function, so the rest of the ORIGINAL code could be left unchanged. The thing about the original code, however, is that no values are needed to be passed down the .then chain, so, even simpler

const promiseTimeout = time => () => new Promise(resolve => setTimeout(resolve, time));

和问题的原始代码 it 块现在可以使用不变

and the original code in the question's it block can now be used unchanged

it('should restore state when browser back button is used',function(done){
  r.domOK().then(function(){
    xh.fire('akc-route-change','/user/4/profile/new');
  }).then(promiseTimeout(2000)).then(function(){
    xu.fire('akc-route-change','/user/6');
  }).then(promiseTimeout(10)).then(function(){
    expect(xu.params[0]).to.equal(6);
    history.back();
  }).then(promiseTimeout(10)).then(function(){
    expect(xu.params[0]).to.equal(4);
    done();
  });
});

这篇关于如何在承诺中包装setTimeout的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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