Javascript 解析链内承诺
我在解决链条内的承诺时遇到了一些问题。在下面的JSBin中,您可以看到我的代码(NodeJS和mongo)。如何从链的两个级别返回数据?下面是代码和JSBINJavascript 解析链内承诺,javascript,node.js,promise,Javascript,Node.js,Promise,我在解决链条内的承诺时遇到了一些问题。在下面的JSBin中,您可以看到我的代码(NodeJS和mongo)。如何从链的两个级别返回数据?下面是代码和JSBIN function test(url) { return new Promise((resolve, reject) => { return scrapeIt({ url: url, headers: { 'User-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x
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)
})
更新1
我的实际代码要长得多,所以我拿出了很多代码,这些代码不是问题产生的必要条件。我修复了urlsToInsert为null的问题。现在还返回urlsToInsert。我已尝试重写最后一部分,但您的代码无法工作,因为您正在将
urlsToInsert
设置为空数组,然后对其进行筛选
您正在返回代码中从未定义过的propertiesToInsert
.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)
}
}
)
)
您有
var urlsToInsert=[]
(空数组)和urlsToInsert=urlsToInsert.filter(…)
(仍然是空数组),因此测试(urlsToInsert&&urlsToInsert.length>0)
肯定是错误的,不是吗?urlsToInsert
应该在哪里填充?我解决了关于urlsToInsert
的问题,基本上只需更改var urlsToInsert=data.urls
。感谢您对@Roamer-1888的观察,据我所知,您在这里使用的方法只有MongoClient.connect()
接受节点回退(因此需要说明)。其他方法返回值:-collection.find().toArray()
返回Array
-.insertMany()
返回document
如果您不知道,请发布文档链接。我解决了有关urlsToInsert
和propertiesToInsert
的问题。基本上只需更改var urlsToInsert=data.urls
和resolve(urlsToInsert)
。对你的答案有疑问,最后我看到它仍然使用dbo,但没有向下传递链。。。它仍然可以访问它吗?@vcliment89 Corect,我更新了答案,因此承诺以不同的方式嵌套,以使dbo在范围内。看起来当最后一个承诺得到解决时,我无法读取此处的数据test('https://www.google.com然后({data,response})=>{console.log(data)}).catch((error)=>{console.log(error)})