Unhandled Rejection: TypeError: Cannot read property 'Symbol(Symbol.iterator)' of undefined
Closed this issue · 4 comments
How to use highlandjs with async await
? Here my code, simple one First i read the csv file, using fast-csv to remove first line and make the and for each line i check it there is a data or not if there is a data its console.log() some message. if not the data saved but. for now if there is a data the data still saved and not console.log() my message. and if every stream is pass it returning same error message
Unhandled Rejection: TypeError: Cannot read property 'Symbol(Symbol.iterator)' of undefined
LIbrary im using :
- Fast-Csv
- Bookshelf
- fs
here the full code :
DescController.CompaniesCsv = async (req, res, next) => {
const file = fs.createReadStream(path.join(req.files[0].path), 'utf8').pipe(csv({headers : true}))
// Read data streams from here with highlandjs
_(file)
.each(async (companyData) => {
// console.log(companyData)
const sectorName = capitalize(companyData.sector);
const companyName = capitalize(companyData.name);
const companyCountry = capitalize(companyData.country);
const getSector = await Sector.get({ name: sectorName });
const getCompany = await Company.get({ name: companyName });
const getCountry = await Country.get({ name: companyCountry });
const [sector, company, country] = await Promise.all([getSector, getCompany, getCountry]);
let serSector;
if(!sector) {
console.log('Please add a sector first on the admin');
} else {
serSector = sector.serialize()
}
let serCountry;
if(!country) {
serCountry = await Country.forge({ name: companyData.name, order: 1 }).save();
} else {
serCountry = country.serialize()
}
if(company) {
console.log('There is a company', company.serialize());
} else {
const saveCompany = await Company.forge({ name: companyData.name, country_id: serCountry.id , user_id: req.user.id }).save();
const insertSector = await CompanySector.forge({ company_id: saveCompany.get('id'), sector_id: serSector.id }).save();
await Promise.all(...insertSector)
}
})
return res.redirect('companies');
}
the full error message :
::ffff:127.0.0.1 - - [08/Dec/2018:08:19:52 +0000] "GET /companies HTTP/1.1" 200 - "http://localhost:4000/companies" "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:65.0) Gecko/20100101 Firefox/65.0"
Unhandled Rejection: TypeError: Cannot read property 'Symbol(Symbol.iterator)' of undefined
at Function.all (<anonymous>)
at _callee2$ (C:\DATA\source\code\build\modules\desc\controller.js:200:44)
at tryCatch (C:\DATA\source\code\node_modules\regenerator-runtime\runtime.js:65:40)
at Generator.invoke [as _invoke] (C:\DATA\source\code\node_modules\regenerator-runtime\runtime.js:303:22)
at Generator.prototype.(anonymous function) [as next] (C:\DATA\source\code\node_modules\regenerator-runtime\runtime.js:117:21)
at step (C:\DATA\source\code\build\modules\desc\controller.js:46:191)
at C:\DATA\source\code\build\modules\desc\controller.js:46:361
at <anonymous>
Solved the problem was on the await Promise.all(...insertSector)
I'm still open for feedback on using async await with highlandjs. thanks
async await works with Promises, so you need to convert highland streams to and from promises to use it. To convert from promises, use the contructor (_(aPromise)
). To convert to promises, use toPromise.
In your example, you can do something like this
DescController.CompaniesCsv = async (req, res, next) => {
const file = fs.createReadStream(path.join(req.files[0].path), 'utf8').pipe(csv({headers : true}))
// Read data streams from here with highlandjs
await _(file)
// Create promises that represent the async computations.
.map(async (companyData) => {
...
})
// Convert the promises to streams and wait for them to complete.
// You can replace flatMap(_) with map(_).merge() or map(_).mergeWithLimit(n) to increase
// the amount of parallelism.
.flatMap(_)
// Throw away all of the results of the promises.
.filter((ignored) => false)
// Convert back to a promise so that you can await it.
// Replace this with resume() if you want to return the redirect before you're done
// with the async work.
.toPromise(Promise)
return res.redirect('companies');
}
@vqvu is this still okay to .each
and not .map
?
Using each
like you did originally is OK if you don't want to wait for the async computations to complete before you do the redirect.