узел.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 3

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. Может быть, это будет немного быстрее.