Javascript 你如何用承诺来包装它
我正在尝试为返回承诺的对象运行测试套件。我想把几个动作连在一起,并且在它们之间有短暂的超时。我认为返回承诺的“then”呼叫将等待承诺兑现,然后再触发下一个链接的then呼叫 我创建了一个函数Javascript 你如何用承诺来包装它,javascript,promise,Javascript,Promise,我正在尝试为返回承诺的对象运行测试套件。我想把几个动作连在一起,并且在它们之间有短暂的超时。我认为返回承诺的“then”呼叫将等待承诺兑现,然后再触发下一个链接的then呼叫 我创建了一个函数 function promiseTimeout (time) { return new Promise(function(resolve,reject){ setTimeout(function(){resolve(time);},time); }); }; 试图用承诺来包装setTim
function promiseTimeout (time) {
return new Promise(function(resolve,reject){
setTimeout(function(){resolve(time);},time);
});
};
试图用承诺来包装setTimeout
然后在我的测试套件中,我调用这样的东西
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
值未定义
我做错了什么;DR-您已将setTimeout正确地包装在承诺中,问题是您使用它的方式不正确
.then(promiseTimeout(2000)).then
不会做你期望的事。then的“签名”是then(函数解析,函数拒绝)
promise的then方法接受两个参数:
承诺。然后(履行承诺,拒绝承诺)
onCompleted和onRejected都是可选参数:
- 如果onCompleted不是函数,则必须忽略它
- 如果onRejected不是函数,则必须忽略它
Promise.resolve('hello')
.then(promiseTimeout(2000))
.then(console.log.bind(console))
vs应如何进行:
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月
多年来,情况发生了很大变化——箭头符号使这变得更加容易
首先,我对允诺的定义不同
const promiseTimeout = time => () => new Promise(resolve => setTimeout(resolve, time, time));
上面返回一个函数,可以调用该函数来创建“承诺延迟”,并解析为时间(延迟长度)。考虑到这一点,我不明白为什么这会非常有用,相反,我想:
const promiseTimeout = time => result => new Promise(resolve => setTimeout(resolve, time, result));
上述内容将与先前承诺的结果相一致(更有用)
但是它是一个返回函数的函数,所以原始代码的其余部分可以保持不变。然而,关于原始代码的一点是,不需要在.then链中传递任何值,因此更简单
const promiseTimeout = time => () => new Promise(resolve => setTimeout(resolve, time));
问题的it
块中的原始代码现在可以原封不动地使用
要使超时按您的需要工作,请编写一个接受延迟的函数,并返回一个适合传递给
然后
的函数
function timeout(ms) {
return () => new Promise(resolve => setTimeout(resolve, ms));
}
像这样使用它:
Promise.resolve() . then(timeout(1000)) . then(() => console.log("got here"););
Promise.resolve(42) . then(timeout(1000)) . then(value => console.log(value));
setTimeoutPromise(3000).then(doSomething)
但是,您可能希望访问导致超时的承诺的解析值。在这种情况下,安排由timeout()
创建的函数传递以下值:
function timeout(ms) {
return value => new Promise(resolve => setTimeout(() => resolve(value), ms));
}
像这样使用它:
Promise.resolve() . then(timeout(1000)) . then(() => console.log("got here"););
Promise.resolve(42) . then(timeout(1000)) . then(value => console.log(value));
setTimeoutPromise(3000).then(doSomething)
这可以在异步函数中使用,执行将等待给定的时间间隔。上面已经回答了这一点,但我觉得这可以通过以下方法轻松完成:
const setTimeoutPromise = ms => new Promise(resolve => setTimeout(resolve, ms))
setTimeoutProise
函数在ms
中接受等待时间,并将其传递给setTimeout
函数。等待时间结束后,将执行传递给promise的resolve方法
可以这样使用:
Promise.resolve() . then(timeout(1000)) . then(() => console.log("got here"););
Promise.resolve(42) . then(timeout(1000)) . then(value => console.log(value));
setTimeoutPromise(3000).then(doSomething)
另一种向
Promise
s添加延迟的方法是扩展Promise
构造函数的属性,而不必预定义或导入辅助函数(我个人最喜欢):
Promise.prototype.delay = function (ms) {
return new Promise(resolve => {
window.setTimeout(this.then.bind(this, resolve), ms);
});
}
我省略了reject
回调,因为这意味着总是resolve
演示
Promise.prototype.delay=函数(毫秒){
log(`[log]以${ms/1000}秒的速度获取数据)`);
返回新承诺(解决=>{
setTimeout(this.then.bind(this,resolve),ms);
});
}
document.getElementById('fetch')。onclick=function(){
const duration=1000*document.querySelector(“#duration[type=“number”]”)值;
//resolve()返回一个承诺
//这只是模拟一些长期运行的后台进程
//所以我们可以增加一些延迟
允诺
.resolve('来自服务器的某些数据')
.延迟(持续时间)
.然后(console.log);
}
从服务器获取数据
您所做的类似于setTimeout(fn(),1000)
而不是setTimeout(fn,1000)
,然后
采用的是一个返回承诺而不是承诺的函数。此外,您可以从它
返回承诺,无需使用done
不明白您的意思,我只是将setTimeout调用更改为setTimeout(resolve,time,time)代码>但这并没有改变任何事情。明白了。与第二种方法一样,虽然我刚刚尝试了这两种方法,但我也整理了promiseTimeout-就像在回应Benjamin Grunbaumyes时所做的评论一样,这很好,但在第一个代码片段中,反复执行function(){return promise.Timeout(n);}
似乎过于冗长,我只想写makePromiseTimeout(n)
。同样的问题,还有更多的ES6语法和/w和w/o原始承诺。我不理解这个答案。去掉新的ES6符号,并将timeout重命名为promiseTimeout,您答案的第一部分似乎与我原来的问题相同,但不起作用。区别在哪里?Mytimeout
函数返回一个函数,该函数返回一个承诺。你原来的一个回复了一个承诺然后
需要一个函数——向它传递一个你正在做的承诺将毫无用处。很抱歉前面的评论——我现在明白你在说什么了。如果不仔细思考并有效地将其翻译回我所理解的Javascript,我发现这个新的ES6符号有点难以理解