我如何一起使用节点Promise和http?

时间:2016-04-23 18:26:21

标签: javascript node.js promise

我正在尝试了解节点中的Promises。我希望能够使用http.request作为承诺。这是我到目前为止所学到的。

我使用setTimeout设置了一个测试用例,如下所示:

var makePromise = (txt, milli) => {
    return new Promise((resolve, reject) => {
        setTimeout(() => {  // fn(cb)
            console.log("I promise to...")
            resolve(txt)
        }, milli)
    });
}

var p = makePromise("Come Home", 3000);
var q = makePromise("Go Shopping", 1000);

var tasks = [p, q];

console.log("Start with ", tasks);

Promise.all(tasks).then((res) => {
    console.log(res);
    console.log("Finish");
})

这很好用。现在我认为我需要做的就是用适当的http.request替换setTimeout函数。但它似乎并不那么简单。

以下是目前的尝试。

var makePromise = (collection, item) => {
    var options = {
        method: "PUT",
        port: 9000,
        host: "localhost",
        path: `/${collection}/item/${item.Label.itemUUID}`,
        headers: {
            "Accept": "application/json",
            "Content-type": "application/json",
            "Content-length": JSON.stringify(req.body).length
        }
    };
    console.log(JSON.stringify(options));

    var httpPromise = new Promise((resolve, reject) => {
        var vot = http.request(options, (votResponse) => {
            var responseBody = [];
            votResponse.on('data', (chunk) => {
                console.log(`Got ${chunk.length} ${chunk}`);
                responseBody.push(chunk);
            });
            votResponse.on('end', () => {
                console.log("End of http");
                console.log("After web proxy like call - raw data: ", Buffer.concat(responseBody).toString());
                responseBody.json = JSON.parse(Buffer.concat(responseBody).toString());
                resolve(responseBody.json);
            });
            votResponse.on('error', (err) => {
                reject(err);
            });
        })
        vot.write(JSON.stringify(item));
        vot.end();
    });
    return httpPromise;
};

我知道像“请求 - 承诺”这样的库可以提供帮助,但我希望在使用库之前更深入地了解本机操作。任何人都可以指出我可以采用这种方法吗?

调用代码如下所示:

var collection = req.params.collection;
var patchInstruction = req.body.patchInstruction;
switch (patchInstruction) {
    case "CASCADE DELETE": 
        console.log("CASCADE DELETE on", collection, req.body.item);
        var tasks = [req.body.item].concat(req.body.asSubject).concat(req.body.asObject);
        tasks = tasks.map((e, i, a) => {
            e.Item = "DELETED"
            return makeDeletePromise(collection, e); // a promise to do the http PUT
        });
        console.log("WIP ", tasks);
        Promise.all(tasks).then((res) => {
            console.log("To client --> ",res);
            res.send(res);  
        })
        break;
    default:    
        console.log("No path to ",patchInstruction);
        res.send(409);
        break;
}

对端口9000的调用永远不会发生。

1 个答案:

答案 0 :(得分:0)

通过catch电话结束承诺链总是一个好主意。否则,在承诺链中发生的任何错误都将被吞噬" - 你根本看不到它。

因此,只要有then,就应该有catch

Promise.all(tasks).then((res) => {
    console.log("To client --> ", res);
    res.send(res);
}).catch((err) => console.log(err));

我相信,错误位于res.send(res)附近,因为http res被本地res遮蔽了。这实际上是responseBody.json,因此没有send方法。