javascript - 如何将 setTimeout 包装在 Promise 中

标签 javascript promise

我正在尝试为返回 promise 的对象运行测试套件。我想将多个操作链接在一起,并在它们之间设置较短的超时时间。我认为返回 promise 的“then”调用将等待 promise 履行,然后再触发下一个链接的 then 调用。

我创建了一个函数

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

尝试将 setTimeout 包装在 Promise 中。

然后在我的测试套件中,我调用类似这样的内容......

    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当 a 从第一个断点继续到第二个断点时,预计会出现两秒的间隙。

相反,它立即到达第二个断点,并且 t 的值此时未定义。

我做错了什么?

最佳答案

TL;DR - 您已将 setTimeout 正确包装在 promise 中,问题是您使用不当

.then(promiseTimeout(2000)).then

不会做你期望的事情。 .then 的“签名”是 then(functionResolved, functionRejected)

A promise’s then method accepts two arguments:

promise.then(onFulfilled, onRejected)

Both onFulfilled and onRejected are optional arguments:

  • If onFulfilled is not a function, it must be ignored.
  • If onRejected is not a function, it must be ignored.

来源:https://promisesaplus.com/#point-21

您没有将函数传递给 then

考虑一下你的做法:

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”

第二个在2秒后输出2000

因此,你应该这样做:

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 月

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

首先,我会以不同的方式定义promiseTimeout

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

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

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

以上将解析为先前 promise 的结果(更有用)

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

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

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

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();
  });
});

关于javascript - 如何将 setTimeout 包装在 Promise 中,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33843091/

相关文章:

node.js 错误处理。将错误消息存储在 err 中,而不是自动将其打印到控制台

javascript - 在移动设备上,如何获取 "enter"以在类型 ="number"输入中提交表单?

javascript - angular 的错误消息 "Failed to instantiate module"仅在资源管理器中

javascript - 通过参数过滤参数,为什么这不起作用?

javascript - bluebird 在一个简单的 for 循环中 promise

Javascript promise 困惑

javascript - 如何为嵌套异步调用创建 Promise

javascript - jQuery 使用 CSS 和 Maximage slider 触发 h1 颜色变化

javascript - Vanilla JavaScript + 多重选择 - 在多项选择中获得相同的值?

node.js - sails.js/waterline 验证错误处理