我需要在“/system/backup/save”和“/file/print”之间暂停。因为否则,在显示“/file”目录的内容之前,备份将不会完成。 现在代码正在执行备份,但它给了我一个尚未备份的文件列表。
const RouterOSAPI = require("node-routeros").RouterOSAPI;
const sleep = require('util').promisify(setTimeout);
var hosts = require('./config.json');
async function backup() {
return new Promise(function (resolve, reject) {
for (let elem of hosts) {
const conn = new RouterOSAPI({
host: elem.host,
user: elem.user,
password: elem.password
})
conn.connect()
.then((client) => {
return conn.write(["/system/backup/save",]).then((data) => {
resolve('COMPLETE - OK');
}).catch((err) => {
reject('ERROR!');
});
sleep(5000);
}).then(() => {
return conn.write("/file/print").then((data2) => {
console.log(data2)
resolve('CHECK - OK');
conn.close();
}).catch((err) => {
reject('ERROR!');
});
}).catch((err) => {
reject('ERROR CONNECT TO ' + elem.name);
});
}
});
}
backup();
通常,使用延迟来等待异步进程完成是一种反模式,您总是会以等待不够长或等待不必要的长时间而告终。前者的问题当然比后者更大,但两者都是问题。如果您有任何方法可以让另一端报告备份完成情况,那将是您最好的选择。看看文档,似乎
conn.write
的承诺在操作完成之前不应该实现,但我只浏览了文档,所以情况可能并非如此。
除此之外:
不要显式创建 Promise,您的
async
函数会自动创建一个 Promise(但您可能不希望这里有 async
函数)
不要将
.then
/.catch
处理程序与 async
函数混合使用;使用await
。
allSettled
给出成功/失败:
const RouterOSAPI = require("node-routeros").RouterOSAPI;
const sleep = require('util').promisify(setTimeout);
var hosts = require('./config.json');
async function backup() {
// Run the hosts in parallel
return await Promise.allSettled(hosts.map(async (host) => {
let conn;
try {
const c = new RouterOSAPI({
host: elem.host,
user: elem.user,
password: elem.password
})
const client = await c.connect();
conn = c;
await conn.write(["/system/backup/save",]);
await sleep(5000); // Only if really unavoidable because the
// backup continues even after the promise
// from `write` is fulfilled
await conn.write("/file/print");
conn = null;
c.close();
} catch (e) {
if (conn) {
try {
conn.close();
} catch {} // Don't let errors in close shadow previous errors
}
throw e;
}
}));
}
backup()
.then(results => {
// Check for status = "rejected" entries in results and report the errors
});
但请注意,由于该函数仅返回来自
allSettled
的承诺,因此您可能根本不需要 async
函数:
const RouterOSAPI = require("node-routeros").RouterOSAPI;
const sleep = require('util').promisify(setTimeout);
var hosts = require('./config.json');
function backup() {
// Run the hosts in parallel
return Promise.allSettled(hosts.map(async (host) => {
let conn;
try {
const c = new RouterOSAPI({
host: elem.host,
user: elem.user,
password: elem.password
})
const client = await c.connect();
conn = c;
await conn.write(["/system/backup/save",]);
await sleep(5000); // Only if really unavoidable because the
// backup continues even after the promise
// from `write` is fulfilled
await conn.write("/file/print");
conn = null;
c.close();
} catch (e) {
if (conn) {
try {
conn.close();
} catch {} // Don't let errors in close shadow previous errors
}
throw e;
}
}));
}
backup()
.then(results => {
// Check for status = "rejected" entries in results and report the errors
});
(这两者之间有一个微妙的区别,如果
hosts.map
抛出错误,会发生什么——也许是因为 hosts
不是一个数组——但这可能并不重要。前者返回一个被拒绝的承诺,后者抛出一个同步错误。)