Javascript 如何使用setInterval()返回承诺

Javascript 如何使用setInterval()返回承诺,javascript,promise,setinterval,Javascript,Promise,Setinterval,我试图以1000ms的速度返回一个Promise对象,但我不确定在Promise中返回的数据在setInterval()回调中时如何访问它 编辑 我似乎不太清楚我的意图,所以我将尝试解释我正在尝试做什么。I进行倒计时,根据规定的结束日期,每1000毫秒进行一次必要的计算 下面是提供返回值的代码,我希望每1000ms返回一个Pormise值: calculateTimeRemaining(endDate: string) { const { secondsInDay, da

我试图以1000ms的速度返回一个Promise对象,但我不确定在Promise中返回的数据在
setInterval()回调中时如何访问它

编辑 我似乎不太清楚我的意图,所以我将尝试解释我正在尝试做什么。I进行倒计时,根据规定的结束日期,每1000毫秒进行一次必要的计算

下面是提供返回值的代码,我希望每1000ms返回一个Pormise值:

calculateTimeRemaining(endDate: string) {
            const { secondsInDay, daysOfYear, secondsInHour, secondsInMinute } = this.unitsOfTime;
            let distance: number =
                (Date.parse(new Date(endDate).toString()) - Date.parse(new Date().toString())) / this.increment;

            if (distance > 0) {
                // Years left
                if (distance >= daysOfYear * secondsInDay) {
                    // 365.25 * 24 * 60 * 60
                    this.timeRemaining.years = Math.floor(distance / (daysOfYear * secondsInDay));
                    distance -= this.timeRemaining.years * daysOfYear * secondsInDay;
                }
                // Days left
                if (distance >= secondsInDay) {
                    // 24 * 60 * 60
                    this.timeRemaining.days = Math.floor(distance / secondsInDay);
                    distance -= this.timeRemaining.days * secondsInDay;
                }
                // Hours left
                if (distance >= secondsInHour) {
                    // 60 * 60
                    this.timeRemaining.hours = Math.floor(distance / secondsInHour);
                    distance -= this.timeRemaining.hours * secondsInHour;
                }
                // Minutes left
                if (distance >= secondsInMinute) {
                    // 60
                    this.timeRemaining.minutes = Math.floor(distance / secondsInMinute);
                    distance -= this.timeRemaining.minutes * secondsInMinute;
                }
                // Seconds left
                this.timeRemaining.seconds = distance;
            }
            return this.timeRemaining;
        }
示例:

    const interval = window.setInterval(() => {
        return new Promise((resolve, reject) => {
            resolve('Hello');
        });
    }, 1000);
interval.then((data) => console.log(data);
之后如何使用
.then()
访问Promise对象

不起作用:

    const interval = window.setInterval(() => {
        return new Promise((resolve, reject) => {
            resolve('Hello');
        });
    }, 1000);
interval.then((data) => console.log(data);

setInterval
已返回一个整数,该整数可用于使用
clearInterval
取消此间隔

const promise = new Promise((resolve, reject) => {
        resolve('Hello');
    });

然后像这样使用它


promise.then((result) => {
 console.log(result) // Says 'Hello' and will not resolve another value if we call it as it has already been resolved
})
也许这就是你想要达到的。 如果你想以1000毫秒的间隔调用它

const getPromiseInstance = () => new Promise((resolve, reject) => {
        resolve(Math.random());
    });

setInterval(() => {
    getPromiseInstance().then((result) => {
      console.log(result)
    })
}, 1000)

您应该看看Observable,它可能会满足您的需要

这取决于您实际要做的事情,异步iterable可能会完成这项工作

不同之处在于,只有在使用最后一个承诺时,异步iterable才会生成下一个承诺。JavaScript中的间隔很棘手,即使没有承诺。他们尝试定期运行回调,但是如果解释器忙,任何回调的执行都可能会延迟。不过,这种延迟不会传播。此外,对于背景选项卡,短时间间隔也将被限制

假设您的代码总是等待使用异步iterable(例如,在
for…of
循环中),您可以执行以下操作:

function delay(t) {
  return new Promise(resolve => setTimeout(resolve, t))
}

async function *interval(t) {
  while(true) {
    let now = Date.now()
    yield "hello"
    await delay(now - Date.now() + t)
  }
}

for await(const greeting of interval(1000)) console.log(greeting)

正如评论中已经提到的,您不能在时间间隔内返回承诺,但可以将其保存在全局对象中,稍后使用

const jobs=[]
常量间隔=设置间隔(()=>{
如果(jobs.length==10){
间隔时间;
}
let job=Promise.resolve(‘新创建的作业’);
推(作业);
console.log('已创建作业')
}, 1000);
设置超时(()=>{
Promise.all(作业).then(数据=>console.log(数据))

}, 1000*15);您所寻找的是可观察的,而不是承诺。有了承诺,您传递给
的回调最多执行一次,因此:

interval.then((data) => console.log(data));
…将不会多次打印“Hello”,即使您更正了代码中的以下错误:

  • setInterval
    回调函数中返回的任何内容都将被忽略
  • setInterval
    不返回承诺,而是一个整数,唯一标识创建的间隔计时器
另一方面,与承诺相反,可观察对象可以发出多个事件

EcmaScript有一个版本,但您可以创建自己的非常简化的版本:

可观察的类{
构造函数(exec){
this.listeners=新集合;
执行官({
next:(value)=>this.listeners.forEach(({next})=>next&&next(value)),
error:(err)=>this.listeners.forEach(({error})=>error&&error(err)),
complete:()=>this.listeners.forEach(({complete})=>complete&&complete()
});
}
订阅(侦听器){
this.listeners.add(listeners);
返回{unsubscribe:()=>this.listeners.delete(listeners)}
}
}
//创造一个可观察的而不是承诺;
常数间隔=新的可观测({next})=>{
setInterval(()=>next(“Hello”),1000;
});
//同意这一观点
const subscription=interval.subscripte({next:(数据)=>console.log(数据)});
//(可选)使用返回的订阅对象停止侦听:
document.querySelector(“按钮”).addEventListener(“单击”,订阅。取消订阅)

停止侦听
对于间隔,您可以这样定义间隔函数

 function interval() {
    return new Promise(function(resolve, reject) {
        setInterval(function() {                 
           resolve('Hello');
        }, 1000)
  })
};
对于间隔,您可以使用以下选项:

方式1:

interval().then((x) => {
   console.log(x);
})

方式2:

const intervalId = setInterval(() => {
   interval().then((x) => {
   console.log(x);
},1000) })

这只是为了在一段时间后停止间隔函数。 如果不再需要间隔,则必须清除间隔

setTimeout(() => {
    clearInterval(intervalId);
}, 10000);

我不确定这是否有帮助,但是;任何函数都可以做成承诺,在这种情况下,可选语法[async关键字]可能对您有用

async function test() {
      return "hello";
}

test().then( returned => console.log(returned)) // logs hello
但是,setInterval()不返回返回值,而是返回“句柄”

句柄=窗口。setInterval(处理程序[,超时[,参数]])

。。。

然而,你可以在设定的时间间隔内做出承诺

interval = window.setInterval(makepromise,1000)
async function makepromise() {
    console.log("hello");
}
//或

但那时候没有地方休息。我们又回到了我们试图避免的回调!但是,在这个函数中,我们可能可以使用wait

最好是让你的计算符合一个承诺,然后你就可以在区间使用then

interval = window.setInterval(gameloop,1000);

    function gameloop(endDate: string) {
        calculateTimeRemaining(endDate: string).then(
//
// my then code goes here.
//
        )
    }

async calculateTimeRemaining(endDate: string) {
            const { secondsInDay, daysOfYear, secondsInHour, secondsInMinute } = this.unitsOfTime;
            let distance: number =
                (Date.parse(new Date(endDate).toString()) - Date.parse(new Date().toString())) / this.increment;

            if (distance > 0) {
                // Years left
                if (distance >= daysOfYear * secondsInDay) {
                    // 365.25 * 24 * 60 * 60
                    this.timeRemaining.years = Math.floor(distance / (daysOfYear * secondsInDay));
                    distance -= this.timeRemaining.years * daysOfYear * secondsInDay;
                }
                // Days left
                if (distance >= secondsInDay) {
                    // 24 * 60 * 60
                    this.timeRemaining.days = Math.floor(distance / secondsInDay);
                    distance -= this.timeRemaining.days * secondsInDay;
                }
                // Hours left
                if (distance >= secondsInHour) {
                    // 60 * 60
                    this.timeRemaining.hours = Math.floor(distance / secondsInHour);
                    distance -= this.timeRemaining.hours * secondsInHour;
                }
                // Minutes left
                if (distance >= secondsInMinute) {
                    // 60
                    this.timeRemaining.minutes = Math.floor(distance / secondsInMinute);
                    distance -= this.timeRemaining.minutes * secondsInMinute;
                }
                // Seconds left
                this.timeRemaining.seconds = distance;
            }
            return this.timeRemaining;
        }
然而,承诺的价值在于避免使用过于复杂的回调方案带来回调地狱。。。其中代码是回调、回调、回调等等

承诺不会像webworker那样在第二个操作系统线程中运行。因此,除非您试图清理回调以使代码可读,或者实际上正在等待某些东西,否则使用承诺没有任何好处


setInterval是一个干净的回调。Gameloop示例并不容易阅读和理解,因为使用了承诺。我建议在这种情况下,它更难阅读。在这一点上。。。除非循环中还有其他等待或一系列不需要同步运行的承诺

承诺只解决一次,因此您想要实现的并不明确我认为您正在寻找的是一个异步Iterabley您不应该返回并在setInterval内运行您的承诺
setInterval
返回间隔引用,它不返回回调的返回。此外,承诺只能解决一次。你想完成什么?你只能
返回
一次,不能