узел.js-взаимная переменная
Я новичок в node.js, так что прежде чем отпустить мой узел.JS app, я должен быть уверен, что он будет работать, как это должно быть.
Допустим, у меня есть переменная массива, и я инициализирую ее в начале моего скрипта
myArray = [];
Затем я извлекаю некоторые данные из внешнего API, храню их внутри myArray и использую метод setInterval () для повторного извлечения этих данных каждые 30 минут:
pullData();
setInterval(pullData, 30*60*1000);
PullData() функция занимает около 2-3 секунд, чтобы закончить.
Клиенты смогут получить myArray, используя это функция:
http.createServer(function(request, response){
var path = url.parse(request.url).pathname;
if(path=="/getdata"){
var string = JSON.stringify(myArray);
response.writeHead(200, {'Content-Type': 'text/plain'});
response.end(string);
}
}).listen(8001);
Итак, я спрашиваю, Может ли произойти следующая ситуация?:
Клиент пытается получить данные с этого узла.сервер js, и в тот же самый момент, данные записываются в myArray функцией pullData (), в результате чего недопустимые данные отправляются клиенту?
Я прочитал некоторую документацию, и я понял, что когда pullData() работает, createServer() не будет отвечать клиентам, пока pullData() не закончит свою работу? Я действительно не очень хорошо понимаю параллельное программирование, так что мне нужно ваше подтверждение, или у вас есть какое-то лучшее решение?
EDIT: вот код моей функции pullData ():
var now = new Date();
Date.prototype.addDays = function(days){
var dat = new Date(this.valueOf());
dat.setDate(dat.getDate() + days);
return dat;
}
var endDateTime = now.addDays(noOfDays);
var formattedEnd = endDateTime.toISOString();
var url = "https://api.mindbodyonline.com/0_5/ClassService.asmx?wsdl";
soap.createClient(url, function (err, client) {
if (err) {
throw err;
}
client.setEndpoint('https://api.mindbodyonline.com/0_5/ClassService.asmx');
var params = {
"Request": {
"SourceCredentials": {
"SourceName": sourceName,
"Password": password,
"SiteIDs": {
"int": [siteIDs]
}
},
"EndDateTime" : formattedEnd
}
};
client.Class_x0020_Service.Class_x0020_ServiceSoap.GetClasses(params, function (errs, result) {
if (errs) {
console.log(errs);
} else {
var classes = result.GetClassesResult.Classes.Class;
myArray = [];
for (var i = 0; i < classes.length; i++) {
var name = classes[i].ClassDescription.Name;
var staff = classes[i].Staff.Name;
var locationName = classes[i].Location.Name;
var start = classes[i].StartDateTime.toISOString();
var end = classes[i].EndDateTime.toISOString();
var klasa = new Klasa(name,staff,locationName,start,end);
myArray.push(klasa);
}
myArray.sort(function(a,b){
var c = new Date(a.start);
var d = new Date(b.start);
return c-d;
});
string = JSON.stringify(myArray);
}
})
});
4 ответа:
Нет, NodeJs не является многопоточным и все выполняется на одном потоке, это означает, кроме неблокирующих вызовов (т. е. IO) все остальное будет задействовать процессор до тех пор, пока он не вернется, и NodeJS абсолютно не возвращает конечный пользователь заполненный массив наполовину, , пока вы делаете только один HTTP-вызов для заполнения вашего массива.
Обновление: Как указывает @RyanWilcox, любой асинхронный (неблокирующий syscall) вызов может подсказать интерпретатору NodeJS покинуть вашу функцию выполнение на полпути и возвращение к нему позже.
В целом: нет.
JavaScript является однопоточным. Пока одна функция работает, никакая другая функция не может быть.
Исключение составляет задержка между функциями, которые обращаются к значению массива.
Например
var index = i; function getNext() { async.get(myArray[i], function () { i++; if (i < myArray.length) { getNext() } }); }
... в этом случае массив может обновляться между вызовами асинхронной функции.
Вы можете смягчить это, создавглубокую копию массива при запуске первой асинхронной операции.
Javascript-однопоточный язык, поэтому вам не нужно беспокоиться о таком виде параллелизма. Это означает, что никакие две части кода не выполняются одновременно. В отличие от многих других языков программирования, javascript имеет другую модель параллелизма, основанную на событийном цикле. Для достижения наилучшей производительности следует использовать неблокирующие операции, обрабатываемые функциями обратного вызова, обещаниями или событиями. Я полагаю, что ваш внешний API предоставляет некоторые асинхронные функции ввода-вывода, что хорошо подходит для узла.JS.
Если вызов pullData не занимает слишком много времени, другим решением является кэширование данных.
Извлекайте данные только тогда, когда это необходимо (например, когда клиент обращается к /getdata). Если он извлечен, вы можете кэшировать данные с меткой времени. Если /getdata вызывается снова, проверьте, если кэшированные данные старше 30 минут, если да, то извлеките снова.
Также синтаксический анализ массива в json..
var string = JSON.stringify(myArray);
..это может быть сделано вне вызова /getdata, поэтому это не обязательно делать для каждого клиента посещение / getdata. Может быть, это будет немного быстрее.