Javascript NodeJS:等待所有承诺完成但从未真正完成的foreach
我和Nodejs一起工作。我有一个forEach,它是异步的,因为我必须在forEach中等待结果。因此,我需要等待forEach完成,然后继续循环的结果。我找到了几种等待forEach的解决方案,其中之一就是使用承诺。但是,我确实这样做了,并且创建了这些承诺,但是,forEach(因此承诺)完成后的代码从未实际执行(console.log未打印)。NodeJS函数结束时没有任何错误 这是我的密码:Javascript NodeJS:等待所有承诺完成但从未真正完成的foreach,javascript,node.js,promise,Javascript,Node.js,Promise,我和Nodejs一起工作。我有一个forEach,它是异步的,因为我必须在forEach中等待结果。因此,我需要等待forEach完成,然后继续循环的结果。我找到了几种等待forEach的解决方案,其中之一就是使用承诺。但是,我确实这样做了,并且创建了这些承诺,但是,forEach(因此承诺)完成后的代码从未实际执行(console.log未打印)。NodeJS函数结束时没有任何错误 这是我的密码: var Client = require('ssh2').Client; // eslint-
var Client = require('ssh2').Client;
// eslint-disable-next-line no-undef
var csv = require("csvtojson");
// eslint-disable-next-line no-undef
var fs = require("fs");
// eslint-disable-next-line no-undef
const config = require('./config.json');
// eslint-disable-next-line no-undef
const os = require('os');
let headerRow = [];
let sumTxAmount = 0;
const filenameShortened = 'testFile';
let csvLists = [];
let csvFile;
const options = {
flags: 'r',
encoding: 'utf8',
handle: null,
mode: 0o664,
autoClose: true
}
var conn = new Client();
async function start() {
const list = await getCSVList();
let content = fs.readFileSync('./temp.json', 'utf8');
content = JSON.parse(content);
var promises = list.map(function(entry) {
return new Promise(async function (resolve, reject) {
if (!content['usedFiles'].includes(entry.filename)) {
const filename = entry.filename;
csvFile = await getCsv(filename);
csvLists.push(csvFile);
console.log('here');
resolve();
} else {
resolve();
}
})
});
console.log(promises)
Promise.all(promises)
.then(function() {
console.log(csvLists.length, 'length');
})
.catch(console.error);
}
start();
“here”只打印一次(不是数组长度为8的8倍),但创建了8个承诺。打印数组长度的下半部分未执行
谁能告诉我我做错了什么?我是否在虚假地使用承诺和forEach,因为我必须在forEach内部进行等待
注意:getCSVList()和getCsv()是从sftp服务器获取CSV的函数:
function getCSVList() {
return new Promise((resolve, reject) => {
conn.on('ready', function () {
conn.sftp(function (err, sftp) {
if (err) throw err;
sftp.readdir(config.development.pathToFile, function (err, list) {
if(err) {
console.log(err);
conn.end();
reject(err);
} else {
console.log('resolved');
conn.end();
resolve(list);
}
})
})
}).connect({
host: config.development.host,
port: config.development.port, // Normal is 22 port
username: config.development.username,
password: config.development.password
// You can use a key file too, read the ssh2 documentation
});
})
}
function getCsv(filename) {
return new Promise((resolve, reject) => {
conn.on('ready', function () {
conn.sftp(function (err, sftp) {
if (err) reject(err);
let csvFile = sftp.createReadStream(`${config.development.pathToFile}/${filename}`, options);
// console.log(csvFile);
conn.end();
resolve(csvFile);
})
}).connect({
host: config.development.host,
port: config.development.port, // Normal is 22 port
username: config.development.username,
password: config.development.password
// You can use a key file too, read the ssh2 documentation
});
});
}
我的控制台中所有控制台日志的输出为:
`➜ node server.js
resolved
[ Promise { <pending> },
Promise { <pending> },
Promise { <pending> },
Promise { <pending> },
Promise { <pending> },
Promise { <pending> },
Promise { <pending> },
Promise { <pending> } ]
here`
`➜ node server.js
断然的
[承诺{},
承诺{},
承诺{},
承诺{},
承诺{},
承诺{},
承诺{},
承诺{}]
这里`
承诺。all
是一个将返回承诺对象的方法,但您不会等待start方法执行
function getCSVList() {
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve([1, 2, 3, 4]);
}, 1000);
});
}
function getCsv(params) {
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve(params);
}, 1000);
});
}
async function start() {
const list = await getCSVList();
const promises = list.map(item => {
return new Promise(async function (resolve, reject) {
const csvFile = await getCsv(item);
console.log('here');
resolve(csvFile);
});
});
return Promise.all(promises);
}
start().then(res => {
console.log(res);
});
把你的问题分解成几个部分,确认它们在过程中起作用 除其他外,您没有正确使用流 我用
ssh2-sftp客户端制作了一个工作示例,因此您可以将其作为起点
工作示例:
祝你好运 可能getCsv
会比getCSVList
更有趣,因为这似乎是它被阻止的地方。@Jefferson我现在添加了它,我想你不是真的从流中读取。您应该订阅它的“数据”事件,或者将其传输到可写流。可能在结束连接之前。varcsvLists
在哪里定义?我试图通过在start()
函数作用域内声明一个const csvLists=[]
本地复制您的代码,它工作得很好…@k0pernikus我这样做了,但随后用户要求更多的代码。所以我加了一句感谢这个想法。我用我的代码尝试了这一点,但“res”从未打印过,然后您可以尝试将csvFile放在resolve方法中。像这样的“resolve(csvFile)”,您不需要将test
包装在新的承诺中。它已经是一个异步函数了。您可以执行list.map(测试)
。然后您可以直接返回Promise.all(list.map(test))
。
var fs = require('fs'); var _ = require('underscore');
var SFTPClient = require('ssh2-sftp-client');
const CONFIG = {
"SSH_CONN_OPTS":{"host":"XXXXXXXX","port":22,"username":"XXXXXXXX","password":"XXXXXXXX"},
"CSV_DIRECTORY":"/var/www/html"
}
//---------------
//.:The order-logic of the script is here
function StartScript(){
console.log("[i] SSH Connection")
LoadValidationFile(()=>{
InitializeSFTP(()=>{ console.log("[+] SSH Connection Established")
ListRemoteDirectory((list)=>{ console.log(`[i] Total Files @ ${CONFIG.CSV_DIRECTORY} : ${list.length}`)
//console.log(list) //:now you have a 'list' of file_objects, you can iterate over to check the filename
var csvFileList = [] //store the names of the files you will request after
_.each(list,(list_entry)=>{ console.log(list_entry)
if(!CONFIG.USED_FILES.includes(list_entry.name)){ csvFileList.push(list_entry.name) }
})
//:now loop over the new final list of files you have just validated for future fetch
GenerateFinalOutput(csvFileList)
})
})
})
}
//.:Loads your validation file
function LoadValidationFile(cb){
fs.readFile(__dirname+'/temp.json','utf8',(err,data)=>{ if(err){throw err}else{
var content = JSON.parse(data)
CONFIG.USED_FILES = content.usedFiles
cb()
}})
}
//.:Connects to remote server using CONFIG.SSH_CONN_OPTS
function InitializeSFTP(cb){
global.SFTP = new SFTPClient();
SFTP.connect(CONFIG.SSH_CONN_OPTS)
.then(()=>{cb()})
.catch((err)=>{console.log("[!] InitializeSFTP :",err)})
}
//.:Get a list of files from a remote directory
function ListRemoteDirectory(cb){
SFTP.list(`${CONFIG.CSV_DIRECTORY}`)
.then((list)=>{cb(list)})
.catch((err)=>{console.log("[!] ListRemoteDirectory :",err)})
}
//.:Get target file from remote directory
function GetRemoteFile(filename,cb){
SFTP.get(`${CONFIG.CSV_DIRECTORY}/${filename}`)
.then((data)=>{cb(data.toString("utf8"))}) //convert it to a parsable string
.catch((err)=>{console.log("[!] ListRemoteDirectory :",err)})
}
//-------------------------------------------
var csvLists = []
function GenerateFinalOutput(csv_files,current_index){ if(!current_index){current_index=0}
if(current_index!=csv_files.length){ //:loop
var csv_file = csv_files[current_index]
console.log(`[i] Loop Step #${current_index+1}/${csv_files.length} : ${csv_file}`)
GetRemoteFile(csv_file,(csv_data)=>{
if(csv_data){csvLists.push(csv_data)}
current_index++
GenerateFinalOutput(csv_files,current_index)
})
}else{ //:completed
console.log("[i] Loop Completed")
console.log(csvLists)
}
}
//------------
StartScript()