如何在两个异步操作之间暂停?

问题描述 投票:0回答:1

我需要在“/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();
javascript node.js asynchronous
1个回答
1
投票

通常,使用延迟来等待异步进程完成是一种反模式,您总是会以等待不够长或等待不必要的长时间而告终。前者的问题当然比后者更大,但两者都是问题。如果您有任何方法可以让另一端报告备份完成情况,那将是您最好的选择。看看文档,似乎

conn.write
的承诺在操作完成之前不应该实现,但我只浏览了文档,所以情况可能并非如此。

除此之外:

  1. 不要显式创建 Promise,您的

    async
    函数会自动创建一个 Promise(但您可能不希望这里有
    async
    函数)

  2. 不要将

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

© www.soinside.com 2019 - 2024. All rights reserved.