使用promises而不是回调

时间:2017-02-17 10:23:00

标签: javascript node.js es6-promise

我已经从learnyounode完成了这个练习,我正在尝试使用ES2015的承诺(或者如果它更容易,可以使用其他库)来重构它。我已经阅读了有关承诺的内容,我认为我理解它们是如何工作的,但我想知道是否可以在以下代码中使用它们以及如何实现它。

我的目标是让代码更易于阅读和理解,并且更好地理解流程中的承诺。

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

4 个答案:

答案 0 :(得分:2)

您可以尝试这样的事情:

&#13;
&#13;
'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);
    });
&#13;
&#13;
&#13;

答案 1 :(得分:1)

你可以做这样的事情,但是你应该知道结果可能不会按照给定输入的顺序返回。

编辑:现在将按照给定的顺序输出数据。

Search:     (>(\d)<)
Replace:    $2$2$2

答案 2 :(得分:1)

虽然为了教育目的而自己实现所有的承诺逻辑可能是有用的,但应该注意的是,对于具有承诺支持的HTTP请求,有很好的模块,例如request-promise

每月下载量超过100万,它被广泛使用,并且是针对此类任务的经过测试的解决方案。我总是建议为任何实际工作使用经过良好测试的解决方案,而不是重新发明轮子。

现在,出于教育目的,我总是建议尽可能多地重新发明轮子。例如,请参阅此答案,了解将基于回调的代码转换为承诺的一些示例:

另请参阅此答案中的所有链接:

您可以使用回调和承诺找到很多相同代码的示例,以便您可以检查差异。

答案 3 :(得分:0)

Node的核心库的接口不是基于承诺的。但是,您可以使用一个简单的函数将接受Node样式回调的函数转换为返回promise的函数。自己写它可能是一个很好的练习。或者在npm找到它。此转换函数通常命名为promisify。它的更高级版本需要一个对象并转换其所有方法。