Node.js 节点的异步问题
我有一个在节点应用程序中运行的函数,由于我不了解如何正确地编写异步代码,所以无法运行该函数。下面是一个函数,它接收电子邮件的配置文件。我想循环浏览每封电子邮件,查看我的数据库中是否存在该用户。如果他们这样做了,我想返回给定的回调并完全存在函数,而不做任何其他事情。如果找不到该用户,我将根据概要文件中给出的信息创建一个新用户,然后返回与新创建的用户相同的回调。到目前为止,该函数按预期工作,只是它创建了一个新用户,即使在我的数据库中已经找到了一个用户。(上面定义了'User'变量,并具有'create'函数。此外,如果可能的话,我希望避免使用'async'节点模块)Node.js 节点的异步问题,node.js,asynchronous,Node.js,Asynchronous,我有一个在节点应用程序中运行的函数,由于我不了解如何正确地编写异步代码,所以无法运行该函数。下面是一个函数,它接收电子邮件的配置文件。我想循环浏览每封电子邮件,查看我的数据库中是否存在该用户。如果他们这样做了,我想返回给定的回调并完全存在函数,而不做任何其他事情。如果找不到该用户,我将根据概要文件中给出的信息创建一个新用户,然后返回与新创建的用户相同的回调。到目前为止,该函数按预期工作,只是它创建了一个新用户,即使在我的数据库中已经找到了一个用户。(上面定义了'User'变量,并具有'creat
这有什么问题吗
function processProfile(profile, callback) {
var existingUser;
var index = 0;
function processNextEmail() {
if(index >= profile.emails.size()) return; //When we've popped nothing exit
var email = profile.emails[index++];
console.log("Searching for user with this email:" + email.value);
existingUser = findUserByEmail(email.value);
if (existingUser) {
console.log("Found the existing user");
callback(null, existingUser);
processEmail();//recursive call to prcess the next email
} else {
console.log("Creating new user");
var newUser = {
id: profile.id,
firstName: profile.name.givenName,
lastName: profile.name.familyName,
email: profile.emails[0].value
};
user.create(newUser, provider, function(err, user) {
if (err) throw err;
callback(null, user);
processNextEmail();//recursive call to process the next email after creating the user and adding it to the database.
});
}
}
processNextEmail();
}
如果需要递归逻辑来不删除电子邮件,可以在processProfile()闭包的范围内进行一个简单的修改,包括一个indice
还要注意,return callback()行实际上什么都不做。从异步执行的函数返回是浪费时间。只要调用回调函数,然后如果愿意,可以调用空返回函数跳过函数的其余部分,但这是不必要的,除非返回影响逻辑流
编辑:事实证明,这个例子太简单了,不太有趣。我用下面的代码作为一些在工作中难以掌握异步代码的人的示例。我认为在node中使用同步代码可以用来收集配置数据。让我们假设配置存储在一个文件中,然后从该文件中获取文件名,并从另一个文件中收集另一层配置数据。我们可以通过两种方式来实现这一点,使用readFileSyn,或者使用readFile。异步版本很棘手,因为我们需要等待第一步完成,因为我们必须从第一个文件中获取文件名,以便知道第二个文件存储在哪里。下面是同步解决方案和异步解决方案的代码
//The synchronous way
function useConfigurationData(configData) {
dosomethinginterestingwith(configData);
}
function getConfigurationData(fileName) {
var fileName2 = fs.readFileSync(fileName);
var configurationData = fs.readFileSync(fileName2);
return configurationData;
}
var fileData = getConfigurationData('someFile');
useConfigurationData(fileData);
//The equivalent async way
function getConfigurationData(fileName, useConfigDataCallBack) {
fs.readFile(fileName, getConfigDataStepTwo);
function getConfigDataStepTwo(err, fileName2) {
fs.readFile(fileName2, getConfigDataStepThree);
}
function getConfigDataStepThree(err, fileData) {
useConfigDataCallBack(fileData);
}
}
getConfigurationData('someFile', useConfigurationData);
请注意,我们提供给getConfigurationData的回调是最后一步。我们也可以只依赖全局定义的getConfigurationData函数,但将其作为回调传递是更好的方式
我喜欢这种语法,是第二个getConfigurationData函数以非常同步的顺序读取的代码。但是,如果您遵循逻辑流程,那么所有这些都是异步运行的。它易于阅读并遵循节点异步I/O模型。对于配置数据,我认为同步选项是可以接受的,但这仍然是如何从异步回调中获取同步行为和语法(ish)的一个很好的演示。是的,不幸的是,这将为数据库中尚未包含的每封电子邮件创建一个用户。每个配置文件可能有多封电子邮件,但只有一个用户。我的目的是查看配置文件中是否有任何电子邮件在我的数据库中,如果没有,那么我只想创建一个用户,列表中有第一封电子邮件。forEach在循环本身中阻塞。因此,每个元素都保证按顺序处理。将您创建的用户添加到数据库中,以便可以通过连续的电子邮件找到该用户。如果用户创建过程是异步的,则可以递归地执行此操作,而不是使用forEach。我将demo.user.create实际将用户添加到数据库中。此功能用于passport模块,以便通过facebook登录。我可以看到,每次我通过facebook登录时,它都会在我的数据库中创建一个具有完全相同信息的新用户。对,这就是我修改它的原因,我看到该user.create接受回调,因此可能是异步的。。。我现在举的例子应该有用。
//The synchronous way
function useConfigurationData(configData) {
dosomethinginterestingwith(configData);
}
function getConfigurationData(fileName) {
var fileName2 = fs.readFileSync(fileName);
var configurationData = fs.readFileSync(fileName2);
return configurationData;
}
var fileData = getConfigurationData('someFile');
useConfigurationData(fileData);
//The equivalent async way
function getConfigurationData(fileName, useConfigDataCallBack) {
fs.readFile(fileName, getConfigDataStepTwo);
function getConfigDataStepTwo(err, fileName2) {
fs.readFile(fileName2, getConfigDataStepThree);
}
function getConfigDataStepThree(err, fileData) {
useConfigDataCallBack(fileData);
}
}
getConfigurationData('someFile', useConfigurationData);