我正在尝试使用nodejs的promises(我正在尝试使用node-promise包);然而,没有任何成功。请参阅以下代码:
var express = require('express'),
request = require('request'),
promise = require('node-promise');
app.get('/promise', function(req, res) {
var length = -1;
new promise.Promise(request(
{uri: "http://www.bing.com"},
function (error, response, body) {
if (error && response.statusCode !== 200) {
console.log("An error occurred when connected to the web site");
return;
}
console.log("I'll return: " + body.length);
length = body.length;
}
)).then(function(result) {
console.log("This is what I got: " + length);
console.log("Done!");
});
res.end();
});
上述代码的输出仅为I'll return: 35857
,不会转到then
部分。
我将代码更改为:
app.get('/promise', function(req, res) {
var length = -1;
promise.when(
request(
{uri: "http://www.bing.com"},
function (error, response, body) {
if (error && response.statusCode !== 200) {
console.log("An error occurred when connected to the web site");
return;
}
console.log("I'll return: " + body.length);
length = body.length;
}
),
function(result) {
console.log("This is what I got: " + length);
console.log("Done!");
},
function(error) {
console.log(error);
}
);
res.end();
});
这次输出是This is what I got: -1
然后是Done!
...看起来这次没有调用“承诺”。
所以:
感谢。
答案 0 :(得分:4)
我不是专家,但我知道这个lib往往受到服务器端和客户端工作的程序员的青睐。
即使你还不知道jQuery的Deferreds,走这条路的好处是:
文档非常好(它包含指向jQuery文档的链接),但您可能很难找到特定于Node的示例。
方法是可链接的。
jQuery Callbacks
也包括在内。
当有一天你需要在客户端进行异步操作时,几乎没有什么可以重新学习 - 概念是相同的,语法几乎是如此。请参阅上面超链接的github页面中的“Correspondances”部分。
我不是node.js的人,所以我在这里猜测,但根据你上面的代码,你可能想要考虑jquery-deferred-for-node的以下几行:
var express = require('express'),
request = require('request'),
Deferred = require('JQDeferred');
function fetch(uri, goodCodes) {
goodCodes = (!goodCodes) ? [200] : goodCodes;
var dfrd = Deferred(); // A Deferred to be resolved/rejected in response to the `request()`.
request(uri, function(error, response, body) {
if (!error) {
var isGood = false;
// Loop to test response.statusCode against `goodCodes`.
for (var i = 0; i < goodCodes.length; i++) {
if (response.statusCode == goodCodes[i]) {
isGood = true;
break;
}
}
if (isGood) {
dfrd.resolve(response.statusCode, body);
} else {
dfrd.reject(response.statusCode, "An invalid response was received from " + uri);
}
} else {
dfrd.reject(response.statusCode, "An error occurred attempting to connect to " + uri);
}
});
// Make promise derived from dfrd available to "consumer".
return dfrd.promise();
};
//...
app.get('/promise', function(req, resp) {
fetch("http://www.bing.com").done(function(statusCode, result) {
console.log("Done! This is what I got: " + result.length);
}).fail(function(statusCode, message) {
console.log("Error (" + statusCode + "): " + message);
});
resp.end();
};
在这里,我尝试编写一个通用实用程序来获取资源,以便可以在外部处理异步响应(或错误)。我认为这大致与你想要达到的目标一致。
出于兴趣,console.log()消息在哪里以node.js结束?
上面,我给了Deferred
一个初始资本,这对于构造函数是常规的
使用jQuery Deferreds,必须有多种方法连续获取()。下面的方法保留fetch()
原样,并引入fetch_()
作为其前端。可能有更简单的方法,但这允许fetch()
保持一般功能,在功能上等同于客户端jQuery.ajax()
。
function fetch_(uri){
return function(){
return fetch(uri, [200]).then(function(statusCode, result){
console.log("Done! This is what I got: " + result.length);
},function(statusCode, message){
console.log("Error (" + statusCode + "): " + message);
});
};
}
注意函数fetch()
返回一个函数。它必须是这样的,因为在调用fetch()
时,我们想要一个未执行的函数,而不是(还)该函数的结果。
现在让我们假设一个uris数组可用。无论应用程序需要什么,都可以进行硬编码或动态构建。
var uris = [
'http://xxx.example.com',
'http://yyy.example.com',
'http://zzz.example.com'
];
现在,可以通过多种方式调用fetch_()
:
//v1. To call `resp.end()` when the fetching process starts.
app.get('/promise', function(req, resp) {
fetch_(uris[0])().then(fetch_(uris[1])).then(fetch_(uris[2]));
resp.end();
});
//v2. To call `resp.end()` when the fetching process has finished.
app.get('/promise', function(req, resp){
fetch_(uris[0])().then(fetch_(uris[1])).then(fetch_(uris[2])).always(resp.end);
});
//v3. As v2 but building a `.then()` chain of any (unknown) length.
app.get('/promise', function(req, resp){
var dfrd = Deferred().resolve();//
$.each(uris, function(i, uri){
dfrd = dfrd.then(fetch_(uri));
});
dfrd = dfrd.always(resp.end);
});
未测试
我对v1和v2更有信心。 v3可能有效。
v2和v3都应该给出完全相同的行为,但v3会针对任意数量的uris进行推广。
一切都可能需要调试。
答案 1 :(得分:3)
我建议使用Q:https://github.com/kriskowal/q。我相信它在其他框架内部使用(比如jQuery延迟实现)。
我认为文件“很好”;语法与其他promise实现一致......并且它有一个节点适配器。
所以你的延迟风格方法:
var deferred = Q.defer();
FS.readFile("foo.txt", "utf-8", function (err, res) {
if (!err) {
deferred.resolve(res);
} else {
deferred.reject(err);
}
});
return deferred.promise;
可以更简洁地写成:
var deferred = Q.defer();
FS.readFile("foo.txt", "utf-8", deferred.makeNodeResolver());
return deferred.promise;