繁体   English   中英

使用承诺而不是回调

[英]Use promises instead of callbacks

我已经从learningyounode完成了本练习,并且尝试使用ES2015的promises(或者更容易的话,使用其他库)来重构它。 我已经阅读了诺言,并且我想我了解了它们的工作原理,但是我想知道是否有可能在以下代码中使用它们以及如何实现它们。

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

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

您可以尝试这样的事情:

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

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

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

const 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 (url)
{
    return new Promise((resolve, reject) => {
        let result = '';
        http.get(url, res => {
            res.on('data', data => result += data);
            res.on('end', () => resolve(result))
        }).on('err', reject);

    });
}

function printResults() {
    for (let result of results) {
        console.log(result);
    }
}

for (let i = 0; i < urls.length; i++) {
    httpGet(urls[i])
        .then(result => {
            results[i] = result;
            if (++count === 3)
                printResults();
        })
        .catch(err => console.log(err));
}

出于教育目的,自己实现所有promise逻辑可能会很有用,但应注意,有一些带有promise支持的HTTP请求的良好模块,例如request-promise

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

现在,出于教育目的,我总是建议尽可能多地重新设计轮子。 例如,有关将基于回调的代码转换为Promise的一些示例,请参见以下答案:

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

您会发现同时使用回调和Promise的许多相同代码的示例,以便您可以检查差异。

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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