0

我需要在“/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();
4

1 回答 1

1

通常,使用延迟来等待异步进程的完成是一种反模式,您最终会要么等待的时间不够长,要么等待的时间过长。前者当然是比后者更大的问题,但两者都是问题。如果您有任何方法让另一端报告备份完成,那将是您最好的选择。查看文档,似乎conn.write在操作完成之前不应该履行承诺,但我只浏览了文档,所以可能情况并非如此。

除此之外:

  1. 不要显式创建承诺,你的async函数会自动创建一个承诺(但你可能不想要一个async函数)

  2. 不要将 using .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它不是数组——但这可能并不重要。前者返回一个被拒绝的承诺,后者抛出一个同步错误。)

于 2020-12-28T16:30:54.510 回答