He completado este ejercicio de learnyounode y estoy tratando de refactorizarlo usando las promesas de ES2015 (o con otras bibliotecas si es más fácil). He leído sobre promesas y creo que entiendo cómo funcionan, pero me gustaría saber si es posible usarlas en el siguiente código y cómo hacerlo.

Mi objetivo es hacer que el código sea más fácil de leer y comprender, y también comprender mejor las promesas en el proceso.

let http = require("http");

if (process.argv.length != 5) {
    throw new Error("Please provide the 3 URLs as a command line arguments");
}

let urls = [];
let results = [];
let count = 0;

for (let i = 2; i <  process.argv.length; i++) {
    urls.push(process.argv[i]);
}

function httpGet(index) {
    let url = urls[index];
    let result = "";

    http.get(url, res => {
        res.on("data", data => {
            result += data;
        });

        res.on('end', () => {
            count += 1;
            results[index] = result;

            if (count === 3) {
                results.forEach(function(result) {
                   console.log(result);
                });
            }
        });
    });

}

for (let i = 0; i < urls.length; i++) {
    httpGet(i);
}
0
Noxxys 17 feb. 2017 a las 13:23

3 respuestas

La mejor respuesta

Podrías probar algo como esto:

'use strict';

const http = require('http');
if (process.argv.length != 5) {
    throw new Error('Please provide the 3 URLs as a command line arguments');
}

let urls = [];
for (let i = 2; i <  process.argv.length; i++) {
    urls.push(process.argv[i]);
}

function httpGet(url) {
    let result = '';
    return new Promise((resolve, reject) => {
        http.get(url, function (res) {
            res.on('error', err => {
                reject(err);
            });
            res.on('data', data => {
                result += data;
            });
            res.on('end', () => {
                //You can do resolve(result) if you don't need the url.
                resolve({url, result});
            });
        })
    });
}

let promises = urls.map(url => httpGet(url));

Promise.all(promises)
    .then(results => {
        console.log(`All done. Results: ${results}`);
    })
    .catch(err => {
        console.error(err);
    });
2
Drakonoved 27 feb. 2018 a las 13:01

Las interfaces de las bibliotecas principales de Node no están basadas en promesas. Sin embargo, puede usar una función simple para convertir una función que acepta una devolución de llamada de estilo Nodo en una función que devuelve una promesa. Escribirlo usted mismo puede ser un buen ejercicio. O encuéntralo en npm. Esta función de conversión generalmente se denomina promisify. Una versión más avanzada toma un objeto y convierte todos sus métodos.

0
thorn̈ 17 feb. 2017 a las 11:28

Si bien puede ser útil implementar toda la lógica de la promesa usted mismo con fines educativos, debe tenerse en cuenta que existen buenos módulos para solicitudes HTTP con soporte de promesa, como request-promise:

Con más de 1 millón de descargas mensuales, es ampliamente utilizado y es una solución probada para este tipo de tareas. Y siempre recomiendo usar una buena solución probada para cualquier trabajo real en lugar de reinventar la rueda.

Ahora, con fines educativos, por otro lado, siempre recomiendo reinventar tantas ruedas como sea posible. Por ejemplo, vea esta respuesta para ver algunos ejemplos de conversión de código basado en devolución de llamada a promesas:

Vea también todos los enlaces de esta respuesta:

Encontrará muchos ejemplos del mismo código utilizando devoluciones de llamada y promesas, para que pueda examinar las diferencias.

1
Community 23 may. 2017 a las 12:24