TL DR - you correctly wrapped setTimeout in a promise, the problem is that you are using it incorrectly
.then(promiseTimeout(2000)).then
will not do what you expect. Then "signature" for .then then(functionResolved, functionRejected)
The promise method then takes two arguments:
Promise. then (completed, rejected)
Both onFulfilled and onRejected are optional arguments:
- If onFulfilled is not a function, it should be ignored.
- If onRejected is not a function, it should be ignored.
source: https://promisesaplus.com/#point-21
You do not pass a function then
Consider how you do it:
Promise.resolve('hello') .then(promiseTimeout(2000)) .then(console.log.bind(console))
against how this should be done:
Promise.resolve('hello').then(function() { return promiseTimeout(2000) }).then(console.log.bind(console))
First exits 'hello' immediately
The second displays 2000 in 2 seconds
Therefore you should do:
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(); }); });
As an alternative:
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(); }); });
EDIT: March 2019
A lot has changed over the years - the arrow marking makes it even easier.
First, I would have defined the promise differently
const promiseTimeout = time => () => new Promise(resolve => setTimeout(resolve, time, time));
The above returns a function that can be called to create a “promise delay” and resolved by time (delay duration). Thinking about it, I don’t understand why it would be very useful, rather I would:
const promiseTimeout = time => result => new Promise(resolve => setTimeout(resolve, time, result));
The above will result in the result of the previous promise (much more useful)
But this is a function that returns a function, so the rest of the ORIGINAL code can be left unchanged. The essence of the source code, however, is that you don’t need to pass values along the .then chain, which is even easier
const promiseTimeout = time => () => new Promise(resolve => setTimeout(resolve, time));
and the original code in question it can now be used without changes
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(); }); });