首页 > 解决方案 > Node.js 中的承诺链

问题描述

我的 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 未定义 已
处理

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

标签: javascriptnode.jspromise

解决方案


目前的代码是:

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. 如果你是返回,它来自回调,所以基本上它不会走出函数。如果你这样做,你将在你的下一个 then 链中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);
});

注意:正如我所说,这是一种非常不优雅的做事方式,我建议使用基于 promise 的库,axios或者使用asynclibrary 而不是 promise。你也可以使用async-await. 他们每个人都是更好的方法。


推荐阅读