router.post('/runCommand', async function(req, res){
let results = [];
async.each(req.body.requests, async function(request, callback){
const data = await connect(request.command)
await results.push(data);
await callback(null);
}, function(err){
if (!err) {
res.send(202, results)
}
})
})
Res.send никогда не выполняется, и кажется, что обратный вызов происходит до завершения подключения. Connect успешно возвращает обещание, потому что это
router.get('/topics', async function(req, res) {
console.info('in get');
const data = await connect(req.body.command);
await res.send(data);
});
работает отлично. Но включение async.each для запуска нескольких команд кажется неработающим. Я знаю, что это проблема с тем, как я вызываю функцию обратного вызова async.each, но исследования не помогли, как я должен ее называть. Можно ли использовать .then() после ожидания обещания?
function connect(command){
return new Promise(function(resolve) {
let host = {
server: {
host: "host",
port: "port",
userName: "user",
password: config.Devpassword
},
commands: [ command ]
};
var SSH2Shell = require ('ssh2shell'),
//Create a new instance passing in the host object
SSH = new SSH2Shell(host),
//Use a callback function to process the full session text
callback = function(sessionText){
console.info(sessionText)
resolve(sessionText);
}
SSH.connect(callback);
})
};
По журналам консоли в функции подключения я могу сказать, что это происходит для каждой команды в req. и да, это правильный формат. Проблема, с которой я сталкиваюсь, связана с запуском обратного вызова. Я не жду подключения для завершения работы. поэтому async.each выполняет каждую команду в req до того, как массив результатов будет правильно определен. Хотя я не уверен, почему res.send никогда не происходит. Я предполагал, что он просто отправит массив невыполненных обещаний, но на самом деле никогда не отправляет
Пожалуйста, предоставьте источник connect(), отправив свой ответ редактироватьRing. Похоже, проблема в этом.
И вы получаете console.info(sessionText) на каждый request в req.body.requests?
@PatrickRoberts Я добавил исходный код для connect(), хотя не верю, что проблема существует. Возвращает обещание штрафа. Когда я запускаю только одну команду с другой функцией, она должным образом ожидает ее завершения перед повторной отправкой текста сеанса. Я думаю, проблема в том, как я вызываю callback () из async.each
да, я попытался передать 3 команды, и журнал консоли появился для всех 3
Попробуйте callback() вместо callback(null). Я был бы удивлен, если это сработает, но это единственное, что кажется возможным здесь изменить. Вы неправильно используете await в нескольких местах, но это не влияет на то, что должно произойти.
@PatrickRoberts, как ни странно, удаление null по крайней мере сделало так, чтобы был вызван res.send. Но он отправил только пустой массив вместо массива sessionTexts. Итак, callback() определенно работает до завершения подключения. Можно ли переформатировать подключение к const data = await connect().then( callback() )
Вы уверены, что опубликованный вами источник router.post() - это то, что вы на самом деле используете? Я не хочу сказать, что задаю очевидный вопрос; Я спрашиваю, потому что спрашивающие обычно удаляют код в опубликованных фрагментах для краткости или по причинам собственности, а иногда эти удаления приводят к тому, что минимальный пример ведет себя иначе.
И нет, предложенное вами изменение не сработает по нескольким причинам.
Да, я дважды проверил. Он идентичен, вплоть до имен функций и переменных.
Я все еще пытаюсь разобраться в этой проблеме. Мне это кажется очень странным.



![Безумие обратных вызовов в javascript [JS]](https://i.imgur.com/WsjO6zJb.png)


Хотя вы могли бы и дальше тратить больше времени на то, чтобы заставить async.each() работать, я рекомендую просто отказаться от него и использовать исключительно синтаксис async / await, который значительно упрощает ваш код:
router.post('/runCommand', async function (req, res) {
try {
const results = await Promise.all(
req.body.requests.map(({ command }) => connect(command))
);
res.send(202, results);
} catch ({ message, stack }) {
res.send(500, { error: message, stack });
}
})
Глядя на документацию ssh2shell, я думаю, что ваша функция connect также может быть улучшена для лучшей читаемости и обработки ошибок:
const SSH2Shell = require('ssh2shell');
function connect (command) {
return new Promise((resolve, reject) => {
const host = {
server: {
host: 'host',
port: 'port',
userName: 'user',
password: config.Devpassword
},
commands: [command]
};
//Create a new instance passing in the host object
const SSH = new SSH2Shell(host);
SSH.on('error', reject);
SSH.connect(resolve);
});
}
Не стесняйтесь комментировать, если это все еще не работает для вас.
Благодарность! Вы были на 100% правы, говоря об упрощении. Я обязательно воспользуюсь этим, но, возможно, изучу async.each, когда у меня будет больше времени.
Вы когда-нибудь звонили на ваш обратный звонок на
async.each()? Если да, то о какой ошибке было сообщено? Здесь недостаточно информации, чтобы определить, в чем вы ошибаетесь. Вы уверены, чтоreq.bodyвашего запроса POST будет отформатирован как{ requests: [ { command: ... }, ...] }?