将 setInterval 转换为 promise

Convert setInterval to promise

你好,我是 javascript 的新手,想知道是否有办法将低于 setInterval 的东西转换成一个 promise,以便可以使用 .then 而不是 callback。有帮助吗?

我的想法:
使用 setTimeout 我可以在固定时间后 resolve。但我对 setInterval 没有任何想法......

function alert_above(scrip, price, callback) {
  var intvl = setInterval(() => {
    if (get_last_price(scrip) > price) {
      callback();
      clearInterval(intvl);
    }
  }, 1000);
 return intvl;
}

我想你可以包装成一个 new Promise 像 :

function promisifySetInterval(time) {
  var defer = new Promise(resolve => {
    let counter = 0
    var intvl = setInterval(() => {
      if (counter > time) {
        resolve('hey');
        clearInterval(intvl);
      } else {
        counter += 1000
      }
    }, 1000);
  })
 return defer;
}

promisifySetInterval(2000).then(param => {
  console.log('hey', param)
})

对于你这样的情况:

function alert_above(scrip, price) {
  var defer = new Promise(resolve => {
    var intvl = setInterval(() => {
      if (get_last_price(scrip) > price) {
        resolve('hey');
        clearInterval(intvl);
      }
    }, 1000);
  })
 return defer;
}

alert_above().then(param => {
  console.log('hey', param)
})

您可以创建异步解析的承诺函数。详细了解 Promise Here

function myInterval() {
  return new Promise(resolve => {
    const intId = setInterval(() => {
      clearInterval(intId);
      resolve();
    }, 1000)
  })
}


myInterval().then(() => {
  console.log('Called after 1 second');
})

注意:poll会在第一次执行时不延迟,与原生的setInterval不同。

问:为什么 poll 基于 setTimeout 而不是 setInterval
答:请参阅 Execute the setInterval function without delay the first time

实施:

// Promisify setTimeout
const pause = (ms, cb, ...args) =>
  new Promise((resolve, reject) => {
    setTimeout(async () => {
      try {
        resolve(await cb?.(...args))
      } catch (error) {
        reject(error)
      }
    }, ms)
  })

// Promisify setInterval
const poll = async (interval, times, cb, ...args) => {
  let result
  const resolve = value => (times = 0) || (result = value)
  const reject = reason => (times = 0) || (result = Promise.reject(reason))
  await (async function basePoll() {
    if (times > 0) {
      const _result = await cb(...args, resolve, reject)
      if (times) {
        result = _result
        --times && (await pause(interval, basePoll))
      }
    }
  })()
  return result
}

测试:

import ordinal from 'ordinal'

// Test 1
poll(1000, 3, (a, b, c) => [a, b, c], 1, 2, 3).then(value => console.log(value))

// Test 2
let times = 0
poll(1000, 5, resolve => {
  console.log(`${ordinal(++times)} time`)
  times === 3 && resolve('resolved')
}).then(value => console.log(value))

// Test 3
let times = 0
poll(1000, 5, (resolve, reject) => {
  console.log(`${ordinal(++times)} time`)
  times === 3 && reject('rejected')
}).catch(error => console.error(error))