我是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服务器获取数据,同时pullData()函数将数据写入myArray,导致无效数据发送到客户端?
我读了一些文档,我意识到当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);
}
})
});
不,NodeJs不是多线程的,所有东西都在一个线程上运行,这意味着除了非阻塞调用(即IO)之外,其他所有东西都会占用CPU,直到它返回,NodeJs绝对不会将填充了一半的数组返回给最终用户,只要你只做一个HTTP调用来填充数组。
更新: 正如@RyanWilcox所指出的,任何异步(非阻塞系统调用)调用都可能提示NodeJS解释器让您的函数执行半途而废,稍后再返回。
一般情况下:无
JavaScript是单线程的。当一个功能正在运行时,没有其他功能可以运行。
例外情况是,访问数组值的函数之间存在延迟。
例如
var index = i;
function getNext() {
async.get(myArray[i], function () {
i++;
if (i < myArray.length) {
getNext()
}
});
}
…在这种情况下,可以在对异步函数的调用之间更新数组。
您可以通过在启动第一个异步操作时创建阵列的深度副本来减轻这种情况。
Javascript是单线程语言,所以您不必担心这种并发性。这意味着没有两部分代码同时执行。与许多其他编程语言不同,javascript有不同的基于事件循环的并发模型。为了获得最佳性能,应该使用回调函数、promise或事件处理的非阻塞操作。我假设您的外部API提供了一些非常适合node.js的异步I/o函数。
如果pullData调用不需要太长时间,另一个解决方案是缓存数据。
仅在需要时获取数据(因此,当客户端访问/getdata时)。如果它被提取,您可以使用时间戳缓存数据。如果再次调用/getdata,请检查缓存的数据是否早于30分钟,如果是,请再次提取。
还将数组解析为json。。
var string = JSON.stringify(myArray);
可能在/getdata调用之外完成,因此不必为每个访问/getdata的客户端执行此操作。可能会稍微快一点。