I'm having some trouble resolving promises inside a chain. In the JSBin below you can see the code I have (NodeJS and mongo). How can I return the data from 2 levels down the chain? Here is the code and JSBIN
function test(url) {
return new Promise((resolve, reject) => {
return scrapeIt({
url: url,
headers: { 'User-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/66.0.3359.139 Safari/537.36' }
}, {
urls: {
listItem: '#list',
data: {
url: {
selector: "span[data-label='url']"
}
}
},
currentPage: {
selector: 'span.current',
convert: x => parseInt(x)
},
pages: {
selector: 'span.pages',
convert: x => parseInt(x)
}
}).then(({ data, response }) => {
return MongoClient.connect(config.db.serverUrl, function (err, db) {
var dbo = db.db(config.db.name)
var urlsToInsert = data.urls
return dbo.collection(config.db.collection).find({ 'url': { '$in': data.urls } }, { projection: { _id: 0 } }).toArray(function (err, res) {
if (res && res.length > 0) {
// Exclude properties already in DB
urlsToInsert = urlsToInsert.filter(x => !res.some(y => x.url == y.url))
if (urlsToInsert && urlsToInsert.length > 0)
return dbo.collection(config.db.collection).insertMany(urlsToInsert, function (err, res) {
console.log("Number of documents inserted: " + res.insertedCount)
db.close()
return urlsToInsert
})
}
})
})
})
})
}
test('https://www.google.com').then(({ data, response }) => {
console.log(data)
}).catch((error) => {
console.log(error)
})
My actual code is much longer so I took out a lot of the code that was not required for the issue to make sense. I fixed the issue with the urlsToInsert being null. Also returning now urlsToInsert.
I have tried to rewrite the last part but your code would not work because you're setting urlsToInsert
to an empty array and then filtering it.
You're returning propertiesToInsert
that's never defined anywhere in your code.
.then(
({ data, response }) =>
new Promise(
(resolve,reject)=>
MongoClient.connect(config.db.serverUrl,(err, db) =>
(err, db) =>
(err)
? reject(err)
: resolve(db.db(config.db.name))
)
)
).then(
dbo=>
new Promise(
(resolve,reject)=>
dbo.collection(config.db.collection).find(
{ 'url': { '$in': data.urls } },
{ projection: { _id: 0 } }
).toArray((err, res) =>
(err)
? reject(err)
: resolve(res)
)
).then(
res=>{
var urlsToInsert = [];
if (res && res.length > 0) {
// Exclude properties already in DB THIS MAKES NO SENSE, FILTERING AN EMPTY ARRAY
urlsToInsert = urlsToInsert.filter(x => !res.some(y => x.url == y.url))
if (urlsToInsert && urlsToInsert.length > 0) {
return new Promise(
(resolve,reject)=>
dbo.collection(config.db.collection).insertMany(urlsToInsert, function (err, res) {
if(err){reject(err);}//this never happens anyway
console.log("Number of documents inserted: " + res.insertedCount);
db.close();
//what are you returning here?
resolve(propertiesToInsert)
})
)
}
return [];//what to return if there are no urls to insert (always because you're filtering empty array)
}
}
)
)
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.