javascript - ¿Cómo puedo encadenar estas funciones junto con las promesas?
node.js request (1)
Si desea encadenar esas funciones con promesas, entonces tienen que devolver las promesas .
Si desea encadenarlos con un módulo
async
, entonces deben
tomar devoluciones de llamada
como argumentos.
En este momento no devuelven una promesa (o cualquier otra cosa), ni toman devoluciones de llamada (o cualquier otra cosa) como argumentos. Si la función no recibe una devolución de llamada y no devuelve nada, entonces todo lo que puede hacer es llamarla y listo. No se le notificará ningún resultado.
Ejemplo
Devoluciones de llamada
Si tiene 3 funciones que aceptan devoluciones de llamada:
function fun1(cb) {
setTimeout(() => {
cb(null, "fun1");
}, 1000);
}
function fun2(cb) {
setTimeout(() => {
cb(null, "fun2");
}, 3000);
}
function fun3(cb) {
setTimeout(() => {
cb(null, "fun3");
}, 100);
}
Entonces puedes saber cuándo terminan:
fun3((err, value) => {
console.log(''fun3 finished:'', value);
});
Y puede esperar fácilmente uno antes de comenzar el otro:
fun1((err1, val1) => {
fun2((err2, val2) => {
console.log("fun1 + fun2:", val1, val2);
});
});
Promesas
Si sus funciones devuelven promesas:
function fun1() {
return new Promise((res, rej) => {
setTimeout(() => {
res("fun1");
}, 1000);
});
}
function fun2() {
return new Promise((res, rej) => {
setTimeout(() => {
res("fun2");
}, 3000);
});
}
function fun3() {
return new Promise((res, rej) => {
setTimeout(() => {
res("fun3");
}, 100);
});
}
Entonces también puedes saber cuándo terminan:
fun3().then(value => {
console.log(''fun3 finished:'', value);
});
También puede anidar fácilmente las llamadas:
fun1().then(val1 => {
fun2().then(val2 => {
console.log("fun1 + fun2:", val1, val2);
});
});
O:
fun1()
.then(val1 => fun2())
.then(val2 => fun3())
.then(val3 => console.log(''All 3 finished in series''));
etc.
Para poder hacer mucho más con ambos estilos, consulte la documentación para:
Este es un programa que elimina los datos del sitio web de una camiseta y luego escribe la información del producto en un archivo CSV.
Hay 3 funciones de raspado y 1 función de escritura.
En este momento, estoy teniendo una pesadilla absoluta tratando de entender cómo implementar promesas aquí sin ninguna biblioteca o paquete de terceros. ¿Es esto posible solo con las características nativas de ES6?
Debido a la naturaleza asíncrona de las solicitudes, necesito que cada función y sus solicitudes finalicen por completo antes de que se llame a la siguiente.
Esto es para que pueda usar las variables como
urlSet
en la siguiente función.
¿Cómo puedo hacer esto simplemente sin reescribir todo mi código?
Debo mencionar que cada una de estas funciones funciona de forma individual, todas han sido probadas varias veces.
¿Cada función se convierte en una promesa individual?
El código está abajo, gracias:
//TASK: Create a command line application that goes to an ecommerce site to get the latest prices.
//Save the scraped data in a spreadsheet (CSV format).
''use strict'';
//Modules being used:
var cheerio = require(''cheerio'');
var json2csv = require(''json2csv'');
var request = require(''request'');
var moment = require(''moment'');
var fs = require(''fs'');
//harcoded url
var url = ''http://shirts4mike.com/'';
//url for tshirt pages
var urlSet = new Set();
var remainder;
var tshirtArray = [];
// First scrape loads front page of shirts4mike and finds the first product pages/menus
function firstScrape(){
request(url, function(error, response, html) {
if(!error && response.statusCode == 200){
var $ = cheerio.load(html);
//iterate over links with ''shirt''
$(''a[href*=shirt]'').each(function(){
var a = $(this).attr(''href'');
//create new link
var scrapeLink = url + a;
//for each new link, go in and find out if there is a submit button.
//If there, add it to the set
request(scrapeLink, function(error,response, html){
if(!error && response.statusCode == 200) {
var $ = cheerio.load(html);
//if page has a submit it must be a product page
if($(''[type=submit]'').length !== 0){
//add page to set
urlSet.add(scrapeLink);
} else if(remainder == undefined) {
//if not a product page, add it to remainder so it another scrape can be performed.
remainder = scrapeLink;
}
}
});
});
}
});
}
//Scrape next level of menus to find remaning product pages to add to urlSet
function secondScrape() {
request(remainder, function(error, response, html) {
if(!error && response.statusCode == 200){
var $ = cheerio.load(html);
$(''a[href*=shirt]'').each(function(){
var a = $(this).attr(''href'');
//create new link
var scrapeLink = url + a;
request(scrapeLink, function(error,response, html){
if(!error && response.statusCode == 200){
var $ = cheerio.load(html);
//collect remaining product pages and add to set
if($(''[type=submit]'').length !== 0){
urlSet.add(scrapeLink);
}
}
});
});
}
});
}
//call lastScraper so we can grab data from the set (product pages)
function lastScraper(){
//scrape set, product pages
for(var item of urlSet){
var url = item;
request(url, function(error, response, html){
if(!error && response.statusCode == 200){
var $ = cheerio.load(html);
//grab data and store as variables
var price = $(''.price'').text();
var imgURL = $(''.shirt-picture'').find(''img'').attr(''src'');
var title = $(''body'').find(''.shirt-details > h1'').text().slice(4);
var tshirtObject = {};
//add values into tshirt object
tshirtObject.Title = title;
tshirtObject.Price = price;
tshirtObject.ImageURL = imgURL;
tshirtObject.URL = url;
tshirtObject.Date = moment().format(''MMMM Do YYYY, h:mm:ss a'');
//add the object into the array of tshirts
tshirtArray.push(tshirtObject);
}
});
}
}
//Convert array of tshirt objects and write to CSV file
function convertJson2Csv(){
//The scraper should generate a folder called `data` if it doesn’t exist.
var dir =''./data'';
if(!fs.existsSync(dir)){
fs.mkdirSync(dir);
}
var fields = [''Title'', ''Price'', ''ImageURL'', ''URL'', ''Date''];
//convert tshirt data into CSV and pass in fields
var csv = json2csv({ data: tshirtArray, fields: fields });
//Name of file will be the date
var fileDate = moment().format(''MM-DD-YY'');
var fileName = dir + ''/'' + fileDate + ''.csv'';
//Write file
fs.writeFile(fileName, csv, {overwrite: true}, function(err) {
console.log(''file saved'');
if (err) throw err;
});
}