Javascript 如何使Node.JS异步
我正在努力思考如何克服和处理Node.JS的异步特性。我对它做了大量的阅读,并试图通过使用消息传递解决方案或回调函数使Node做我想做的事情 我的问题是我有一个对象,我想在其中使用构造函数加载文件并填充数组。然后我希望对这个函数的所有调用都使用加载的数据。因此,我需要原始调用等待文件加载,所有后续调用使用已加载的私有成员 我的问题是,加载数据并获取数据的函数是异步执行的,即使它返回带有回调的函数也是如此 不管怎样,有什么简单的东西我错过了吗?或者这里有没有更简单的模式?此函数应返回加载文件的一部分,但返回未定义的文件。我已经检查了文件是否确实正在加载,并且工作正常Javascript 如何使Node.JS异步,javascript,node.js,asynchronous,Javascript,Node.js,Asynchronous,我正在努力思考如何克服和处理Node.JS的异步特性。我对它做了大量的阅读,并试图通过使用消息传递解决方案或回调函数使Node做我想做的事情 我的问题是我有一个对象,我想在其中使用构造函数加载文件并填充数组。然后我希望对这个函数的所有调用都使用加载的数据。因此,我需要原始调用等待文件加载,所有后续调用使用已加载的私有成员 我的问题是,加载数据并获取数据的函数是异步执行的,即使它返回带有回调的函数也是如此 不管怎样,有什么简单的东西我错过了吗?或者这里有没有更简单的模式?此函数应返回加载文件的一部
函数歌(){
这节经文=未定义;
this.loadVerses=函数(verseNum,回调){
如果(this.verses==未定义){
var fs=require('fs'),
文件名='README.md';
fs.readFile(文件名'utf8',函数(错误,数据){
如果(错误){
log('打开文件时出错:%s,错误:%s',文件名,错误];
犯错误;
}否则{
这是数据;
返回回调(verseNum);
}
});
}否则{
返回回调(verseNum);
}
}
this.getVerse=函数(verseNum){
返回这个。第[verseNum+1]节;
}
}
Song.prototype={
诗句:功能(输入){
返回this.loadVerses(输入,this.getVerse);
}
}
module.exports=新歌曲();
更新:
这就是我如何使用另一个模块的歌曲模块
var song = require('./song');
return song.verse(1);
“我的问题是,加载数据并获取数据的函数正在异步执行,即使它返回带有回调的函数。”
@AlbertoZaccagni我所说的场景是,这行返回this.loadVerses(输入,this.getVerse)当我希望文件等待回调时,代码>在加载文件之前返回
这就是node的工作原理,我将尝试用一个例子来说明它
function readFile(path, callback) {
console.log('about to read...');
fs.readFile(path, 'utf8', function(err, data) {
callback();
});
}
console.log('start');
readFile('/path/to/the/file', function() {
console.log('...read!');
});
console.log('end');
您正在读取一个文件,并且在控制台中可能有
- 开始
- 即将阅读
- 结束
- …读李>
您可以单独尝试以查看它的实际效果,并对其进行调整以了解要点。这里需要注意的是,您的代码将继续运行,跳过回调的执行,直到读取文件为止
声明回调并不意味着执行将停止,直到调用回调然后恢复
这就是我将如何更改代码:
function Song() {
this.verses = undefined;
this.loadVerses = function(verseNum, callback) {
if (this.verses === undefined) {
var fs = require('fs'),
filename = 'README.md';
fs.readFile(filename, 'utf8', function(err, data) {
if (err) {
console.log('error throw opening file: %s, err: %s', filename, err);
throw err;
} else {
this.verses = data;
return callback(verseNum);
}
});
} else {
return callback(verseNum);
}
}
}
Song.prototype = {
verse: function(input, callback) {
// I've removed returns here
// I think they were confusing you, feel free to add them back in
// but they are not actually returning your value, which is instead an
// argument of the callback function
this.loadVerses(input, function(verseNum) {
callback(this.verses[verseNum + 1]);
});
}
}
module.exports = new Song();
要使用它:
var song = require('./song');
song.verse(1, function(verse) {
console.log(verse);
});
我忽略了
我们没有将错误作为回调的第一个参数
事实上,要求速度足够快将创造比赛条件,但我相信这是另一个问题
“我的问题是,加载数据并获取数据的函数正在异步执行,即使它返回带有回调的函数。”
@AlbertoZaccagni我所说的场景是,这行返回this.loadVerses(输入,this.getVerse)当我希望文件等待回调时,代码>在加载文件之前返回
这就是node的工作原理,我将尝试用一个例子来说明它
function readFile(path, callback) {
console.log('about to read...');
fs.readFile(path, 'utf8', function(err, data) {
callback();
});
}
console.log('start');
readFile('/path/to/the/file', function() {
console.log('...read!');
});
console.log('end');
您正在读取一个文件,并且在控制台中可能有
- 开始
- 即将阅读
- 结束
- …读李>
您可以单独尝试以查看它的实际效果,并对其进行调整以了解要点。这里需要注意的是,您的代码将继续运行,跳过回调的执行,直到读取文件为止
声明回调并不意味着执行将停止,直到调用回调然后恢复
这就是我将如何更改代码:
function Song() {
this.verses = undefined;
this.loadVerses = function(verseNum, callback) {
if (this.verses === undefined) {
var fs = require('fs'),
filename = 'README.md';
fs.readFile(filename, 'utf8', function(err, data) {
if (err) {
console.log('error throw opening file: %s, err: %s', filename, err);
throw err;
} else {
this.verses = data;
return callback(verseNum);
}
});
} else {
return callback(verseNum);
}
}
}
Song.prototype = {
verse: function(input, callback) {
// I've removed returns here
// I think they were confusing you, feel free to add them back in
// but they are not actually returning your value, which is instead an
// argument of the callback function
this.loadVerses(input, function(verseNum) {
callback(this.verses[verseNum + 1]);
});
}
}
module.exports = new Song();
要使用它:
var song = require('./song');
song.verse(1, function(verse) {
console.log(verse);
});
我忽略了
我们没有将错误作为回调的第一个参数
事实上,要求速度足够快将创造比赛条件,但我相信这是另一个问题
[收集到答案中,并根据我以前的评论进行了扩展]
TL;DR您需要对代码进行结构化,以便任何操作的结果只在该操作的回调中使用,因为您在其他任何地方都无权访问它
虽然将其分配给外部全局变量肯定会按预期工作,但这样做只会在启动回调后发生,而回调发生在您无法预测的时间
评论
回调不会返回值,因为从本质上讲,回调是在将来的某个时候执行的
将回调函数传递给控制异步函数后,将在周围函数决定调用它时执行它。您无法控制此操作,因此等待返回的结果将不起作用
您的示例代码,song.verse(1)
不能返回任何有用的内容,因为它会立即被调用,而且由于回调尚未启动,它只会返回它能返回的唯一值:null
我担心这种对带有已传递回调的异步函数的依赖是NodeJS运行方式的一个不可改变的特性;这是它的核心
不过不要灰心。对所有NodeJS问题的快速调查清楚地表明,只有在回调中才能处理异步操作的结果,这是理解如何在NodeJS中编程的最大障碍
有关正确构造的各种方法的非常优秀的解释/教程