简体   繁体   中英

Resolve promise inside chain

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)
})

JSBin snippet

Update 1

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM