Javascript 如何在两个异步操作之间暂停?
我需要在“/system/backup/save”和“/file/print”之间暂停。否则,在显示“/file”目录的内容之前,备份将无法完成。 现在代码正在执行备份,但它给了我一个还没有备份的文件列表Javascript 如何在两个异步操作之间暂停?,javascript,node.js,asynchronous,mikrotik,router-os,Javascript,Node.js,Asynchronous,Mikrotik,Router Os,我需要在“/system/backup/save”和“/file/print”之间暂停。否则,在显示“/file”目录的内容之前,备份将无法完成。 现在代码正在执行备份,但它给了我一个还没有备份的文件列表 const RouterOSAPI = require("node-routeros").RouterOSAPI; const sleep = require('util').promisify(setTimeout); var hosts = require('./con
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
的承诺不应该兑现,但我只是浏览了一下文档,所以可能不是这样
除此之外:
async
函数会自动创建承诺(但您可能不希望在此处使用async
函数)
。然后
/。用异步
函数捕获
处理程序;使用等待
allsolited
返回承诺,因此您可能根本不需要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
不是一个数组),这两者之间会有细微的区别,但这可能并不重要。前者返回一个被拒绝的承诺,后者抛出一个同步错误。)而不是sleep>。使用承诺等待行动完成。避免错误!resolve()
和reject()
调用将无法在该循环中正常工作。另一端是否无法告诉您备份何时完成?另外:如果你有一个async
函数,你不需要显式地创建承诺,而且你通常不想使用。然后等附加处理程序(改为使用wait
)。sleep(5000)
做什么?它创造了一个承诺,你必须返回这个承诺!尽管@John是正确的,但你不应该在那里睡觉,而应该等待写作完成。
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
});