javascript - 所有 setTimeout 完成后节点脚本不退出
问题描述
我有这个脚本可以更改我们用于测试目的的现有 FireBase 身份验证用户的所有密码,以便将用户重置为“干净”状态。
var admin = require('firebase-admin');
// Input args
var jsonKey = process.argv[2];
var projectId = process.argv[3];
var newPassword = process.argv[4];
var serviceAccount = require(jsonKey);
admin.initializeApp({
credential: admin.credential.cert(serviceAccount),
databaseURL: "https://" + projectId + ".firebaseio.com"
});
// FIXME Only for debug purposes
var index = 1;
/**
* https://firebase.google.com/docs/auth/admin/manage-users#update_a_user
*/
function nextUser(uid, timeout) {
setTimeout(() => {
admin.auth().updateUser(uid, {
password : newPassword
})
.then(function() {
console.log(index++ + ') Successfully updated user', uid);
})
.catch(function(error) {
console.log(index++ + ') Error updating user:', error);
});
}, timeout);
}
/**
* https://firebase.google.com/docs/auth/admin/manage-users#list_all_users
* https://stackoverflow.com/a/58028558
*/
function listAllUsers(nextPageToken) {
let timeout = 0;
admin.auth().listUsers(1000, nextPageToken)
.then(function (listUsersResult) {
console.log("Retrieved " + listUsersResult.users.length + " users");
listUsersResult.users.forEach(function (userRecord) {
timeout = timeout + 100
nextUser(userRecord.uid, timeout)
});
if (listUsersResult.pageToken) {
listAllUsers(listUsersResult.pageToken);
}
})
.catch(function (error) {
console.log('Error listing users:', error);
});
}
listAllUsers();
该脚本是从本地计算机启动的
node <filename.js> <path of jsonkey> <projectid> <new password>
正如您所看到的,迭代器正在超时运行,这是在我遇到“超过更新帐户信息的配额”的问题后需要的,我试图用这个答案解决这个问题
脚本运行良好,所有用户都被正确处理(我只为这种调试添加了一个顺序计数器)并且没有抛出“配额”错误。问题是,在脚本结束时,shell 提示符没有退出,进程仍然挂起,我需要一个CTRL+C
来杀死它。除了这种行为令人讨厌的部分之外,这还阻止了一个更广泛的脚本,该脚本调用这个脚本并且不会继续执行下一行命令。
似乎在setTimeout
执行了所有功能之后,主进程并没有自动关闭。
我该如何解决这个问题?
编辑
我尝试了不同的方法:
- https://repl.it/repls/RoundedAnchoredDos,不起作用,firebase-app 在所有用户被处理之前被删除
- https://repl.it/repls/DelightfulUnfoldedHexagon,有效,它是一个同步版本,一次处理一个用户,在最后一个用户firebase被删除后
第二个版本有效,但速度很慢。所以我从初始脚本开始,我添加了一个“监视器”,等待所有用户完成(使用非常脏的计数器)并在最后关闭脚本
var admin = require('firebase-admin');
// Input args
var jsonKey = process.argv[2];
var projectId = process.argv[3];
var newPassword = process.argv[4];
var serviceAccount = require(jsonKey);
admin.initializeApp({
credential: admin.credential.cert(serviceAccount),
databaseURL: "https://" + projectId + ".firebaseio.com"
});
// Index to count all users that have been queued for processing
var queued = 0;
// Index to count all user that have completed the task
var completed = 0;
/**
* https://firebase.google.com/docs/auth/admin/manage-users#update_a_user
*/
function nextUser(uid, timeout) {
setTimeout(() => {
/* ------ Process User Implementation ------ */
admin.auth().updateUser(uid, {
password : newPassword
})
.then(function() {
console.log(++completed + ') Successfully updated user ', uid);
})
.catch(function(error) {
console.log(++completed + ') Error updating user:', error);
});
/* ------ Process User Implementation ------ */
}, timeout);
queued++;
}
/**
* https://firebase.google.com/docs/auth/admin/manage-users#list_all_users
* https://stackoverflow.com/a/58028558
*/
function listAllUsers(nextPageToken) {
let timeout = 0;
admin.auth().listUsers(1000, nextPageToken)
.then(function (listUsersResult) {
console.log("Retrieved " + listUsersResult.users.length + " users");
listUsersResult.users.forEach(function (userRecord) {
timeout = timeout + 100
nextUser(userRecord.uid, timeout)
});
if (listUsersResult.pageToken) {
listAllUsers(listUsersResult.pageToken);
} else {
waitForEnd();
}
})
.catch(function (error) {
console.log('Error listing users:', error);
});
}
function waitForEnd() {
if(completed < queued) {
console.log("> " + completed + "/" + queued + " completed, waiting...");
setTimeout(waitForEnd, 5000);
} else {
console.log("> " + completed + "/" + queued + " completed, exiting...");
admin.app().delete();
}
}
listAllUsers();
有效,速度很快。对我来说足够了,因为它是一个测试脚本
解决方案
尝试将以下退出代码放在 setTimeout 函数之后。
process.exit() // exit
我更新了代码。
function listAllUsers(nextPageToken) {
let timeout = 0;
admin.auth().listUsers(1000, nextPageToken)
.then(function (listUsersResult) {
console.log("Retrieved " + listUsersResult.users.length + " users");
listUsersResult.users.forEach(function (userRecord) {
timeout = timeout + 100
nextUser(userRecord.uid, timeout)
});
if (listUsersResult.pageToken) {
listAllUsers(listUsersResult.pageToken);
}
process.exit(0); // exit script with success
})
.catch(function (error) {
console.log('Error listing users:', error);
process.exit(1); // exit script with failure
});
}
此函数将退出 Node.js 脚本。
process.exit([code]) 以指定的代码结束进程。如果省略,则退出使用“成功”代码 0。
使用“失败”代码退出:
process.exit(1);
执行节点的 shell 应该看到退出代码为 1。
官方文档:https ://nodejs.org/api/process.html#process_exit_codes
推荐阅读
- android - 在 FirestoreRecyclerAdapter 上使用接口实现 onLongClick
- android - 与谷歌地图上的兴趣点互动
- python - 不知道如何在 windows 中的多个文件上运行
- android - 使用回收站视图更新实时数据库中的特定项目
- google-sheets - 如何在单独的列中在谷歌表中为日、月和年制作下拉菜单
- javascript - 如何在ajax中提交多个值?
- viro-react - 我的 ViroReact 安装过程卡在“加载依赖关系图,完成”
- python - 如何使用标签列表索引 DateTimeIndex
- python - 在python中解析二维数组
- python - Python - 将 Python 模块添加到 Windows 上 py Installer 编译的 .exe 文件中