【发布时间】:2016-08-22 12:53:47
【问题描述】:
我正在编写一个 Node.js 应用程序:
- 接受文件(来自 HTTP“POST”),然后
- 将文件写入 Box.com 存储库。
这个从 HTTP“POST”消息中读取文件数据的 Node.js 代码完美运行:
// ORIGINAL (non-Promise; parse only)
app.post('/upload', function(req,res) {
console.log('/upload...');
var form = new multiparty.Form ();
form.parse(req, function(err, fields, files) {
res.writeHead(200, {'content-type': 'text/plain'});
res.write('received upload:\n\n');
res.end(util.inspect({fields: fields, files: files}));
});
问题是读取文件数据只是我需要做的几件事中的第一个,所有这些都涉及异步回调。所以我尝试使用promises 来序列化调用(根据需要优雅地处理错误):
var Promise = require('bluebird');
...
// IDEAL SOLUTION (using "promises")
var data = {};
try {
parsePostMsg(req, data))
.then(sendAck(res, data))
.then(writeTempFile())
.then(sendToBox())
.then(deleteTempFile());
} catch (e) {
console.log("app.post(/upload) ERROR", e);
deleteTempFile();
}
问题:
第一个函数parsePostMsg() 本身有一个回调。永远不会被调用:
function parsePostMsg(req, data) {
console.log("parsePostMsg...");
return new Promise(function(resolve, reject) {
var form = new multiparty.Form ();
form.parse(req, function(err, fields, files) {
data.fields = fields; // <-- This never gets called, so fields & files
data.files = files; // never get initialized!
});
});
}
问:我如何正确地 1) 创建承诺,然后 2) 调用 parsePostMsg() 以便 3) form.parse() 正确地沿链被调用?
问:我是否在正确的地方正确地创建了“承诺”????
问:resolve() 和 reject() 呢?它们适合哪里?
================================================ ========================
附录:我尝试了很多东西,到目前为止都没有任何效果。
目标:让这些函数(及其相关的回调,如果适用)按此顺序运行:
- parsePostMsg(req, data) // 等待“解析表单数据”回调完成
- sendAck(res, data) // 同步
- writeTempFile(data) // 构建 HTTP 消息,发送,等待远程服务器响应
- deleteTempFile(data) // 一切完成后清理
这是一个失败的例子:
/*
* If the "timeout" values are the same (e.g. "10"), everything works fine.
*
* But if the timeout values are *different*, the order gets scrambled:
* Invoking parsePostMsg...
* ... OK ...
* Done: data= {}
* writeTemp@setting data.temp { temp: 'foo' }
* sendAck@acknowledging {} { temp: 'foo' }
* deleteTempFile@callback: data.temp was foo
* parsePostMsg@setting data.{fields, files} {} { temp: undefined, fields: [], files: [] }
*/
var Promise = require('bluebird');
var req = {}, res = {}, data = {};
var temp;
function parsePostMsg(req, data) {
console.log("parsePostMsg...");
return new Promise(function(resolve, reject) {
setTimeout(function() {
data.fields = [];
data.files = [];
console.log("parsePostMsg@setting data.{fields, files}", req, data);
resolve();
}, 35);
});
}
function sendAck(req, data) {
console.log("sendAck...");
return new Promise(function(resolve, reject) {
setTimeout(function() {
console.log("sendAck@acknowledging", req, data);
resolve();
}, 5);
});
}
function writeTempFile(data) {
console.log("writeTemp...");
return new Promise(function(resolve, reject) {
setTimeout(function() {
data.temp = "foo";
console.log("writeTemp@setting data.temp", data);
resolve();
}, 2);
});
}
function deleteTempFile(data) {
console.log("deleteTemp...");
return new Promise(function(resolve, reject) {
setTimeout(function() {
console.log("deleteTempFile@callback: data.temp was ", data.temp);
data.temp = undefined;
resolve();
}, 15);
});
}
console.log("Invoking parsePostMsg...");
parsePostMsg(req, data)
.then(sendAck(res, data))
.then(writeTempFile(data))
.then(deleteTempFile(data));
console.log("Done: data=", data);
【问题讨论】:
-
要使用 Promise,您的所有异步操作都必须是“;promisified”,并返回一个 Promise,当异步操作成功完成时使用该值解析,或者如果操作失败则拒绝并说明原因。跨度>
标签: javascript node.js callback promise