Мой скрипт автоматически получает данные от API и сохраняет их в MongoDB. Мне нужно было создать задержку не менее 2 секунд, прежде чем получать одни данные за другими. Проблема в том, что мой скрипт перестал работать второй раз. Допустим, у меня скрипт работает каждый час, я включаю скрипт в 14.00 - он работает, а в 15.00 - останавливается. Я начинаю исследовать проблему и прихожу к выводу, что проблема с setTimeout()
внутри al oop.
Это статья, которую я нашел Остерегайтесь при использовании SetTimeout(
) в For L oop # JS
Эта строка Пакет Node-Schedule Он в основном вызывает скрипт каждые 15 минут (если кому-то интересно, что это такое)
const j = schedule.scheduleJob('*/15 * * * *', callIt)
Моя цель: как я могу изменить свой код, чтобы он все еще имел задержку в 2 секунды и рабочий л oop. Есть ли альтернативы для использования вместо setTimeout()
, возможно, мне просто нужно поместить setTimeout()
в другое место в коде, или, может быть, есть даже какие-то пакеты, которые я могу добавить дополнительно.
Проблема c область кода:
var symbols = ["ZRXBTC", "ETHBTC", "ETCBTC", "KAVABTC", "AEBTC"]
];
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, 2000)
})
.catch((err) => {
console.log(err);
})
};
ПОЛНЫЙ КОД
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", "ETHBTC", "ETCBTC", "KAVABTC", "AEBTC"]
];
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, 2000)
})
.catch((err) => {
console.log(err);
})
};
const j = schedule.scheduleJob('*/15 * * * *', 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();
});
});
};
РЕДАКТИРОВАТЬ1: Чтобы быть более правильным Уточню задачу. Мой пакет node-schedule предполагает вызывать сценарий каждые 15 минут, а я хочу вызывать свойства в массиве каждые 2 секунды. Мне нужно вызывать свойства из массива каждые 2 секунды, иначе я получу IP-запрет от Binance API для вызова API на много / быстро.
EDIT2 Хорошо. setInterval()
для меня не решение. Поскольку мне нужно вызывать скрипт каждые 15 минут, он должен go через массив, и когда он вызывает все свойства из массива, он должен остановиться. В setInterval()
после вызова всех свойств в массиве он снова запускается, к сожалению, это не то, что мне нужно.
EDIT3: Я протестировал несколько вариантов из ответов ниже, все они приводят меня к та же проблема, что сценарий не может запуститься во второй раз или сценарий начинает работать сразу или повторяется даже после завершения свойств массива. Тем не менее, спасибо за ответы, но моя проблема все еще одна.
В настоящее время я пытаюсь использовать методы async / await. Но я получаю сообщение об ошибке: await is only valid in async function
EDIT4 : Итак, это решение с полным кодом от @yoavmatchulsky. Скрипт начинает работать, но я не получаю никаких данных или чего-то такого. Это похоже на работу - но ничего не происходит. Ошибок нет, ничего.
var requestPromise = require('request-promise');
const { MongoClient } = require('mongodb');
const schedule = require('node-schedule');
var XMLHttpRequest = require("xmlhttprequest").XMLHttpRequest;
const fetch = require("node-fetch");
const symbols = ["ZRXBTC", "ETHBTC", "ETCBTC", "KAVABTC", "AEBTC"];
const sleep = async(timeout) => {
return new Promise(resolve => {
setTimeout(resolve, timeout);
});
}
const callIt = async(symbol) => {
return fetch(`https://api.binance.com/api/v3/klines?symbol=${symbol}&interval=30m&limit=1`)
.then(res => res.json())
.then(data => async() => {
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);
await saveToDatebase(btcusdtdata);
})
.catch((err) => {
console.log(err);
})
};
const saveToDatebase = async function(BTCdata) {
return new Promise((resolve, reject) => {
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) {
return reject(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) {
return reject(error);
}
console.log('1 document inserted');
db.close();
resolve();
});
});
});
};
const run = async() => {
let cnt = 0;
while (cnt < symbols.length) {
await callIt(symbols[cnt]);
await sleep(2000);
cnt++;
}
}
const j = schedule.scheduleJob('*/2 * * * *', run);