【问题标题】:How to stop setTimeout inside a loop如何在循环内停止 setTimeout
【发布时间】:2020-06-19 11:13:22
【问题描述】:

这是来自该线程的一个继续问题 - setTimeout inside a loop, stops script from working

我有一个脚本,它从 API 接收数据并将其存储在 MongoDB 集合中。 问题是setTimeout() 不允许脚本第二次运行。 我 99.9% 确定问题出在这上面。

问题概述 - Watch Out When Using SetTimeout() in For Loop #JS

有问题的代码区:

const callIt = () => {


    fetch(`https://api.binance.com/api/v3/klines?symbol=${symbols[cnt]}&interval=30m&limit=1`)
        .then(res => res.json())
        .then(data => {
            const btcusdtdata = data.map(d => {
                return {
                    Open: parseFloat(d[1]),
                    High: parseFloat(d[2]),
                    Low: parseFloat(d[3]),
                    Close: parseFloat(d[4]),
                    Volume: parseFloat(d[5]),
                    Timespan: 30,
                }
            });
            console.log(btcusdtdata);
            saveToDatebase(btcusdtdata);
            cnt++;
            if (cnt < symbols.length) setTimeout(callIt, 3000)  
        })
        .catch((err) => {
            console.log(err);

        })

};

此脚本正在调用 API,然后通过数组接收符号。 setTimeout() 遍历整个数组后如何停止?

我试图添加类似clearTimeout(callIt) 的内容对我不起作用。

EDIT1

错误:-TypeError: data.map is not a function

全码

var requestPromise = require('request-promise');
const { MongoClient } = require('mongodb');
const schedule = require('node-schedule');
var XMLHttpRequest = require("xmlhttprequest").XMLHttpRequest;
const fetch = require("node-fetch");



var symbols = ["ZRXBTC",
    "LENDBTC",
    "AEBTC",
    "AIONBTC",
    "ALGOBTC",
    "ARDRBTC",];
let cnt = 0;
    const callIt = () => {
    fetch(`https://api.binance.com/api/v3/klines?symbol=${symbols[cnt]}&interval=30m&limit=1`)
        .then(res => res.json())
        .then(data => {
            const btcusdtdata = data.map(d => {
                return {
                    Open: parseFloat(d[1]),
                    High: parseFloat(d[2]),
                    Low: parseFloat(d[3]),
                    Close: parseFloat(d[4]),
                    Volume: parseFloat(d[5]),
                    Timespan: 30,
                }
            });
            console.log(btcusdtdata);
            saveToDatebase(btcusdtdata);
            cnt++;
            if (cnt < symbols.length) setTimeout(callIt, 3000)
        })
        .catch((err) => {
            console.log(err);

        })

};
const j = schedule.scheduleJob('*/1 * * * *', callIt)

const saveToDatebase = function(BTCdata) {

    const url = 'mongodb+srv://username:password@cluster0-1kunr.mongodb.net/<dbname>?retryWrites=true&w=majority';

    var today = new Date();
    var date = today.getFullYear() + '-' + (today.getMonth() + 1) + '-' + today.getDate();
    var time = today.getHours() + ":" + today.getMinutes() + ":" + today.getSeconds();
    var dateTime = date + ' ' + time;

    MongoClient.connect(url, { useNewUrlParser: true, useUnifiedTopology: true }, (err, db) => {
        if (err) throw err;
        const dbo = db.db('CryptoCurrencies');
        const myobj = { Name: symbols[cnt - 1], Array: BTCdata, Date: dateTime };
        dbo.collection(`${symbols[cnt - 1]}`).insertOne(myobj, (error, res) => {
            if (error) throw error;
            console.log('1 document inserted');
            db.close();
        });
    });

};

【问题讨论】:

  • if (cnt &lt; symbols.length) 不会负责停止脚本吗?为什么你需要一个额外的clearTimeout
  • @Tibebes.M 基本上。该脚本第一次运行,但是当它应该第二次启动时给了我一个错误。我将使用完整的代码示例编辑主要问题。
  • timer = setTimeout(); ... clearTimeout(timer) - 您传递的是回调而不是超时索引
  • “当它应该开始时给我一个错误” - 总是,总是包括错误细节。
  • @Justinas 你能否提供示例原因当我尝试你的代码时(也许我做错了)它会立即启动脚本,但它假设每小时开始使用 node-schedule 包工作

标签: javascript typescript ecmascript-6 settimeout


【解决方案1】:

我在另一篇文章中为你写的脚本,你称之为有问题,在没有任何 clearTimeout 的情况下工作 - 正在发生其他事情

如果需要,您可以在 db.close(); 之后移动 if (cnt &lt; symbols.length) setTimeout(callIt, 3000);

const symbols = ["ZRXBTC",
"LENDBTC",
"AEBTC",
"AIONBTC",
"ALGOBTC",
"ARDRBTC",];
cnt = 0
const callIt = () => {
  console.log(`https://api.binance.com/api/v3/klines?symbol=${symbols[cnt]}&interval=30m&limit=1`)
  cnt++;
  if (cnt < symbols.length) setTimeout(callIt, 3000);
  else console.log("done!")
};
callIt()

【讨论】:

  • 这对我也有用。如果可以,请查看已编辑的问题。
  • 你说上面的代码有问题。我说它按设计工作
  • 如果需要,您可以在 db.close(); 之后添加 if (cnt &lt; symbols.length) setTimeout(callIt, 3000);
  • 我在db.close(); 之后添加对我也不起作用。第一次工作,第二次停止工作。
  • TypeError: data.map 不是函数
猜你喜欢
  • 2012-01-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-10-14
  • 2014-12-31
  • 1970-01-01
  • 1970-01-01
  • 2022-01-11
相关资源
最近更新 更多