Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/361.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 你如何用承诺来包装它_Javascript_Promise - Fatal编程技术网

Javascript 你如何用承诺来包装它

Javascript 你如何用承诺来包装它,javascript,promise,Javascript,Promise,我正在尝试为返回承诺的对象运行测试套件。我想把几个动作连在一起,并且在它们之间有短暂的超时。我认为返回承诺的“then”呼叫将等待承诺兑现,然后再触发下一个链接的then呼叫 我创建了一个函数 function promiseTimeout (time) { return new Promise(function(resolve,reject){ setTimeout(function(){resolve(time);},time); }); }; 试图用承诺来包装setTim

我正在尝试为返回承诺的对象运行测试套件。我想把几个动作连在一起,并且在它们之间有短暂的超时。我认为返回承诺的“then”呼叫将等待承诺兑现,然后再触发下一个链接的then呼叫

我创建了一个函数

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,您答案的第一部分似乎与我原来的问题相同,但不起作用。区别在哪里?My
timeout
函数返回一个函数,该函数返回一个承诺。你原来的一个回复了一个承诺
然后
需要一个函数——向它传递一个你正在做的承诺将毫无用处。很抱歉前面的评论——我现在明白你在说什么了。如果不仔细思考并有效地将其翻译回我所理解的Javascript,我发现这个新的ES6符号有点难以理解