Node.js中的Promise链接

时间:2019-06-26 21:22:44

标签: javascript node.js promise

我的promise-then链似乎没有等待每个先前的return语句。

new Promise(function (resolve, reject) {
    console.log("1");
    const http = require('http');
    http.get(url, (resp) => {
        let data = '';
        resp.on('data', (chunk) => {
            data += chunk;
        });
        resp.on('end', () => {
            var info;
            // process data
            resolve(info);
        });

    }).on("error", (err) => {
        console.log("Error: " + err.message);
    });

}).then(function (info) { 
    console.log("2");
    if (info.item) {
        console.log("item exists, don't retry");
        return (info);
    }
    const http = require('http');
    http.get(url, (resp) => {
        let data = '';
        resp.on('data', (chunk) => {
            data += chunk;
        });
        resp.on('end', () => {
            var info;
            // process data
            return(info);
        });

    }).on("error", (err) => {
        console.log("Error: " + err.message);
    });
}).then(function (info) { 
    console.log("3");
    const http = require('http');
    http.get('otherurl' + info.item, (resp) => {
        let data = '';
        resp.on('data', (chunk) => {
            data += chunk;
        });
        resp.on('end', () => {
            console.log("processed");
            return (info);
        });

    }).on("error", (err) => {
        console.log("Error: " + err.message);
    });

}).then(function (info) {
    console.log("4 " + info);
});

我希望我的输出为:

  

1
  2
  3
  已处理
  4 [someinfo]

这就是我得到的:

  

1
  2
  3
  4个未定义
  已处理

似乎只有第一个承诺-然后异步发生。为什么第二个和第三个then语句不等待先前的返回?

2 个答案:

答案 0 :(得分:2)

当前代码为:

new Promise(function (resolve, reject) {
    console.log("1");
    return(http.ClientRequest)

}).then(function (info) { 
    console.log("2");

    return(http.ClientRequest)

}).then(function (info) { 
    console.log("3");
    resolve(http.ClientRequest)

}).then(function (info) {
    console.log("4 " + info);
});

要开展Promise链,需要return部分then做出承诺。但是您从return then来的任何事情都被视为应许。但就您而言

  1. 您什么都没退。
  2. 如果要返回,它是从回调中返回的,因此基本上它不会超出函数的范围。如果执行return http.get(...),则在下一个然后的链中将得到http.ClientRequest个对象。不是实际数据。

因此,在您的情况下,执行此操作的粗略方法将是:保证每个http调用的成功。

new Promise(function (resolve, reject) {
    console.log("1");
    const http = require('http');
    http.get(url, (resp) => {
        let data = '';
        resp.on('data', (chunk) => {
            data += chunk;
        });
        resp.on('end', () => {
            var info;
            // process data
            resolve(info);
        });

    }).on("error", (err) => {
        console.log("Error: " + err.message);
    });

}).then(function (info) {
    console.log("2");
    if (info.item) {
        console.log("item exists, don't retry");
        return (info);
    }
    return new Promise(function (resolve, reject) {
        const http = require('http');
        http.get(url, (resp) => {
            let data = '';
            resp.on('data', (chunk) => {
                data += chunk;
            });
            resp.on('end', () => {
                var info;
                // process data
                resolve(info);
            });

        }).on("error", (err) => {
            console.log("Error: " + err.message);
        });
    })

}).then(function (info) {
    console.log("3");
    return new Promise(function (resolve, reject) {
        const http = require('http');
        http.get('otherurl' + info.item, (resp) => {
            let data = '';
            resp.on('data', (chunk) => {
                data += chunk;
            });
            resp.on('end', () => {
                console.log("processed");
                resolve(info);
            });

        }).on("error", (err) => {
            console.log("Error: " + err.message);
        });
    })

}).then(function (info) {
    console.log("4 " + info);
});

注意:正如我所说的那样,这是一种非常不优雅的处理方式,我建议您使用基于承诺的库,例如axios或使用async库而不是承诺。您也可以使用async-await。他们每个人都是更好的方法。

答案 1 :(得分:1)

您只是在兑现您的第一个诺言。 当您在回调中返回值时,您将无法解决承诺。 您需要使用与第一个相同的策略,将回调包装在Promise上。因此,在第2步和第3步中,您应该返回一个新的Promise并在回调中解决它。

wb

如果要使用Promise,应尽量避免使用使用回调的模块。您可以使用诸如request-promise或axios之类的方法。