【问题标题】:JavaScript - dispatch 10 promises in every minute?JavaScript - 每分钟发送 10 个承诺?
【发布时间】:2017-07-07 15:54:26
【问题描述】:

如何每分钟发送 10 个 promise?

我在列表中有这些动态日期:

var dates = ["2016-08-31T23:00:00.000Z","2016-09-01T23:00:00.000Z","2016-09-02T23:00:00.000Z","2016-09-03T23:00:00.000Z","2016-09-04T23:00:00.000Z","2016-09-05T23:00:00.000Z","2016-09-06T23:00:00.000Z","2016-09-07T23:00:00.000Z","2016-09-08T23:00:00.000Z","2016-09-09T23:00:00.000Z","2016-09-10T23:00:00.000Z","2016-09-11T23:00:00.000Z","2016-09-12T23:00:00.000Z","2016-09-13T23:00:00.000Z","2016-09-14T23:00:00.000Z","2016-09-15T23:00:00.000Z","2016-09-16T23:00:00.000Z","2016-09-17T23:00:00.000Z","2016-09-18T23:00:00.000Z","2016-09-19T23:00:00.000Z","2016-09-20T23:00:00.000Z","2016-09-21T23:00:00.000Z","2016-09-22T23:00:00.000Z","2016-09-23T23:00:00.000Z","2016-09-24T23:00:00.000Z","2016-09-25T23:00:00.000Z","2016-09-26T23:00:00.000Z","2016-09-27T23:00:00.000Z","2016-09-28T23:00:00.000Z","2016-09-29T23:00:00.000Z","2016-09-30T23:00:00.000Z","2016-10-01T23:00:00.000Z"];

我想获取与这些日期相关的内容或结果。但我不想一次搞定,而是每分钟每10个,直到日期不再。

这是我的工作代码:

     var promises = dates.map(function (date, i) {
        return getContent(date);
    });

    Promise.all(promises).then((data) => {
        console.log(data);
    }).catch((err) => {
        console.log(err.message);
    });

它连续获取内容,不完全是我想要的。

但是有可能实现我的需要吗?有什么想法吗?

注意事项:

getContent(date) 包含大量的async await 承诺,所以在那个调用它的promse.all 中我猜也必须是promise,否则我可以在一个地方获取所有返回数据(即@987654327 @) 当承诺结束时。

编辑:

const delayValue = (val, ms) => {
    new Promise(resolve => {
        setTimeout(resolve.bind(null, val), ms)
    });
}

【问题讨论】:

  • 如果每分钟的数据量真的很重要,我不会为此使用承诺。我会使用setInterval 并在所有数据消失后清除间隔。
  • Promise 不是用于随着时间的推移完成工作,而是用于在完成某些工作后处理某事。并且可能会根据工作的结果做一些不同的事情。我会重新考虑您的代码以及您实际想要实现的目标。即使是下面的答案也只是一个 hack,可以让 Promise 做你想做的事情,而不是他们打算做的事情。
  • @trincot 我认为他们的意思是他们有一个数据数组,他们希望每 6 秒对每个索引执行一次操作,直到数据消失。
  • 在你处理数组的过程中,数组是否是动态的,它可能会增长?举例来说,假设您在 2 分钟内处理了数组中的 20 个项目,但在此期间,数组中又添加了 6 个元素。另外,getContent() 函数是否在执行异步工作(例如等待 I/O;HTTP 请求、数据库调用等)?
  • @teelou 然后是静态的。那么,在你处理日期的过程中,我不会长大?

标签: javascript promise es6-promise


【解决方案1】:

一个 Promise 只解析一次,所以如果你需要每分钟都有结果,并且想用 Promise 做到这一点,你需要对每个数据块有一个单独的 Promise。

您可以通过以下方式使用自定义 delayValue 函数重复创建承诺:

const delayValue = (val, ms) => 
    new Promise(resolve => setTimeout(resolve.bind(null, val), ms));

async function loopDates(dates, chunk, delay) {
    for (let i = 0; i < dates.length; i += chunk) {
        console.log(await delayValue(dates.slice(i, i+chunk), i ? delay : 0));
    }
}

var dates = ["2016-08-31T23:00:00.000Z", "2016-09-01T23:00:00.000Z", "2016-09-02T23:00:00.000Z", "2016-09-03T23:00:00.000Z", "2016-09-04T23:00:00.000Z", "2016-09-05T23:00:00.000Z", "2016-09-06T23:00:00.000Z", "2016-09-07T23:00:00.000Z", "2016-09-08T23:00:00.000Z", "2016-09-09T23:00:00.000Z", "2016-09-10T23:00:00.000Z", "2016-09-11T23:00:00.000Z", "2016-09-12T23:00:00.000Z", "2016-09-13T23:00:00.000Z", "2016-09-14T23:00:00.000Z", "2016-09-15T23:00:00.000Z", "2016-09-16T23:00:00.000Z", "2016-09-17T23:00:00.000Z", "2016-09-18T23:00:00.000Z", "2016-09-19T23:00:00.000Z", "2016-09-20T23:00:00.000Z", "2016-09-21T23:00:00.000Z", "2016-09-22T23:00:00.000Z", "2016-09-23T23:00:00.000Z", "2016-09-24T23:00:00.000Z", "2016-09-25T23:00:00.000Z", "2016-09-26T23:00:00.000Z", "2016-09-27T23:00:00.000Z", "2016-09-28T23:00:00.000Z", "2016-09-29T23:00:00.000Z", "2016-09-30T23:00:00.000Z", "2016-10-01T23:00:00.000Z"];

loopDates(dates, 10, 2000);
.as-console-wrapper { max-height: 100% !important; top: 0; }

现在要将getContent 因素添加到其中,您可以像以前一样执行map(尽管可以缩短语法),然后在每个块上应用Promise.all

const delayValue = (val, ms) => 
    new Promise(resolve => setTimeout(resolve.bind(null, val), ms));

// Mock for getContent:
const getContent = date => Promise.resolve(date);
    
async function loopDates(dates, chunk, delay) {
    const promises = dates.map(getContent);
    
    for (let i = 0; i < dates.length; i += chunk) {
        console.log(await delayValue(Promise.all(promises.slice(i, i+chunk)), 
                                     i ? delay : 0));
    }
}

var dates = ["2016-08-31T23:00:00.000Z", "2016-09-01T23:00:00.000Z", "2016-09-02T23:00:00.000Z", "2016-09-03T23:00:00.000Z", "2016-09-04T23:00:00.000Z", "2016-09-05T23:00:00.000Z", "2016-09-06T23:00:00.000Z", "2016-09-07T23:00:00.000Z", "2016-09-08T23:00:00.000Z", "2016-09-09T23:00:00.000Z", "2016-09-10T23:00:00.000Z", "2016-09-11T23:00:00.000Z", "2016-09-12T23:00:00.000Z", "2016-09-13T23:00:00.000Z", "2016-09-14T23:00:00.000Z", "2016-09-15T23:00:00.000Z", "2016-09-16T23:00:00.000Z", "2016-09-17T23:00:00.000Z", "2016-09-18T23:00:00.000Z", "2016-09-19T23:00:00.000Z", "2016-09-20T23:00:00.000Z", "2016-09-21T23:00:00.000Z", "2016-09-22T23:00:00.000Z", "2016-09-23T23:00:00.000Z", "2016-09-24T23:00:00.000Z", "2016-09-25T23:00:00.000Z", "2016-09-26T23:00:00.000Z", "2016-09-27T23:00:00.000Z", "2016-09-28T23:00:00.000Z", "2016-09-29T23:00:00.000Z", "2016-09-30T23:00:00.000Z", "2016-10-01T23:00:00.000Z"];

loopDates(dates, 10, 2000);
.as-console-wrapper { max-height: 100% !important; top: 0; }

【讨论】:

  • 抱歉,我对这个const delayValue = (val, ms) =&gt; new Promise(resolve =&gt; setTimeout(resolve.bind(null, val), ms)); 有疑问 - 为什么我不能用括号括起来?如果我这样做,我会得到undefined。请参阅我上面的编辑。谢谢。
  • 箭头函数有两种语法:我使用了表达式语法,其中表达式是返回值。如果添加 大括号,则转向语句块语法:在这种情况下,您必须在表达式之前使用 return
【解决方案2】:

如果你坚持使用 Promise,那么创建一个设置了超时解析器的 Promise。

在里面弹出数组并做任何你喜欢的事情。承诺所有这些承诺都会起到我认为的作用。

但是为什么要承诺而不是设置超时的简单 for 循环呢?

【讨论】:

  • getContent(date) 包含大量的async await 承诺。所以在那一点上,我猜它也必须是一个承诺。但似乎不可能分块。
猜你喜欢
  • 2021-02-08
  • 1970-01-01
  • 2023-03-16
  • 1970-01-01
  • 1970-01-01
  • 2020-11-24
  • 1970-01-01
  • 2016-09-28
  • 1970-01-01
相关资源
最近更新 更多