2015-03-17 4 views
2

Я пытаюсь обернуть голову вокруг обещаний. Для базовых понятий я понимаю, но как только он становится вложенным, я немного смущен. Любая обратная связь оцененаИзменить async рабочий процесс на Promise (Bluebird)

Вот код, который я пытаюсь реорганизовать в Обещания (Bluebird)

var getIndividualData = function(url, doneGetIndividualData) { 
    var $, data; 

    request(url, function(err, res, body) { 
     if (!err && res.statusCode === 200) { 
      $ = cheerio.load(body); 

      data = { 
       title: $("#itemTitle").children()["0"].next.data, 
       condition: $("#vi-itm-cond").text(), 
       price: $("#prcIsum_bidPrice").text(), 
       imgUrl: $("#icImg")[0].attribs.src, 
       createdAt: chance.date(), 
       likes: chance.integer({min: 0, max: 1000}) 
      }; 

      doneGetIndividualData(null, data); 
     } else { 
      doneGetIndividualData(err); 
     } 
    }); 
}; 

var getListing = function(url, doneGetListing) { 
    var $; 
    var links = []; 

    request(url, function(err, res, body) { 
     if (!err && res.statusCode === 200) { 
      $ = cheerio.load(body); 

      $('.vip').each(function(i, el) { 
       if (i < 15) { 
        links.push(el.attribs.href); 
       } 
      }); 

      async 
       .concat(links, getIndividualData, function(err, result) { 
        return doneGetListing(null, result); 
       }); 
     } else { 
      doneGetListing(err); 
     } 
    }); 
}; 

var putToMongo = function(err, result) { 
    if (devConfig.seedDB) { 
     mongoose.connect(devConfig.mongo.uri); 

     Item.find({}).remove(function(err, items) { 
      Item.create(result, function(err, items) { 
       console.log('done'); 
       process.kill(); 
      }); 
     }); 
    } 
}; 

async 
    .concat(urls, getListing, putToMongo); 
+1

Итак, в чем вопрос? –

ответ

2

Первое, что нужно сделать, это обернуть request в чем-то, что возвращает обещание. Многие библиотеки обещают есть утилиты для «promisifying» асинхронное функции, но я не думаю, что буду работать здесь, потому что request проходит два успешных значения в его функции обратного вызова:

var requestAsync = function(url) { 
    return new Promise(function (resolve, reject) { 
     request(function (err, res, body) { 
      if (err) { 
       reject(err); 
      } 
      resolve({ res: res, body: body}); 
     }); 
    }); 
}; 

Как только это сделано, это становится намного проще:

var getIndividualData = function(url) { 
    return requestAsync(url).then(function (result) { 
     if (result.res.statusCode === 200) { 
      var $ = cheerio.load(result.body); 

      return { 
       title: $("#itemTitle").children()["0"].next.data, 
       condition: $("#vi-itm-cond").text(), 
       price: $("#prcIsum_bidPrice").text(), 
       imgUrl: $("#icImg")[0].attribs.src, 
       createdAt: chance.date(), 
       likes: chance.integer({min: 0, max: 1000}) 
      }; 
     } 

     throw new Error("Individual data status code: " + result.res.statusCode); 
    }); 
}; 

var getListing = function(url, doneGetListing) { 
    return requestAsync(url).then(function (result) { 
     if (result.res.statusCode === 200) { 
      var $ = cheerio.load(result.body), 
       promises = $('.vip').filter(function (i) { 
        return i < 15; 
       }).map(function (i, el) { 
        return getIndividualData(el.attribs.href); 
       }); 

      return Promise.all(promises); 
     } 

     throw new Error("Listing status code: " + result.res.statusCode); 
    }); 
}; 

var putToMongo = function(result) { 
    if (devConfig.seedDB) { 
     mongoose.connect(devConfig.mongo.uri); 

     Item.find({}).remove(function(err, items) { 
      Item.create(result, function(err, items) { 
       console.log('done'); 
       process.kill(); 
      }); 
     }); 
    } 
}; 

Promise.all(urls.map(getListing)) 
.then(putToMongo) 
.catch(function (err) { 
    // handle error 
}); 
+0

большое спасибо !! это именно то, что мне нужно. –

Смежные вопросы