node.js - взаимная переменная

Я новичок в node.js, поэтому перед выпуском моего приложения node.js я должен быть уверен, что оно будет работать так, как должно.

Допустим, у меня есть переменная массива, и я инициализирую ее в начале моего скрипта

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);

Итак, что я спрашиваю, может ли случиться следующая ситуация?: клиент пытается получить данные с этого сервера node.js, и в этот же момент данные записываются в myArray с помощью функции pullData(), что приводит к неверным данным отправлено клиенту?

Я прочитал некоторую документацию, и я понял, что при запуске pullData() createServer() не будет отвечать клиентам, пока pullData() не завершит свою работу? Я действительно плохо разбираюсь в параллельном программировании, поэтому мне нужно ваше подтверждение по этому поводу, или если у вас есть какое-то лучшее решение?

РЕДАКТИРОВАТЬ: вот код моей функции 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, любой асинхронный (неблокирующий системный вызов) вызов может дать подсказку интерпретатору NodeJS прекратить выполнение функции на полпути и вернуться к ней позже.

В общем: нет.

JavaScript является однопоточным. Пока работает одна функция, другой функции быть не может.

Исключение составляют случаи, когда у вас есть задержки между функциями, которые обращаются к значению массива.

например

var index = i;
function getNext() {
    async.get(myArray[i], function () {
        i++;
        if (i < myArray.length) {
            getNext()
        }
    });
}

… В этом случае массив может обновляться между вызовами асинхронной функции.

Вы можете уменьшить это, создав глубокую копию массива при запуске первой асинхронной операции.

Javascript - это однопоточный язык, так что вам не нужно беспокоиться о таком параллелизме. Это означает, что никакие две части кода не выполняются одновременно. В отличие от многих других языков программирования, в JavaScript есть другая модель параллелизма, основанная на цикле событий. Чтобы добиться максимальной производительности, вы должны использовать неблокирующие операции, обрабатываемые функциями обратного вызова, обещаниями или событиями. Я полагаю, что ваш внешний API предоставляет некоторые функции асинхронного ввода-вывода, которые хорошо подходят для node.js.

Если ваш вызов pullData не занимает много времени, другое решение - кэшировать данные.

Получать данные только при необходимости (например, когда клиент обращается к /getdata). Если он получен, вы можете кэшировать данные с отметкой времени. Если /getdata вызывается снова, проверьте, не старше ли кэшированные данные, чем 30 минут, если это так, извлеките снова.

Также разбор массива в json.

var string = JSON.stringify(myArray);

... может быть сделано вне вызова /getdata, так что это не нужно делать для каждого клиента, посещающего /getdata. Может сделать это немного быстрее.

Другие вопросы по тегам