在nodejs中承诺有麻烦
我正在尝试使用nodejs的承诺(我试图与节点承诺包); 然而,没有任何成功。 请参阅下面的代码:
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
,它不会去那个部分。
我改变代码然后是:
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!
看起来这个“诺言”这次没有被调用。
所以:
- 需要做些什么来修复上面的代码? 显然我没有做对:)
- 是节点承诺“走的路”,当我承诺,还是有更好的方式/包? 即更简单和更多生产就绪。
谢谢。
尝试jQuery的延迟节点 。
我不是专家,但明白,这个lib往往受到服务器端和客户端的程序员的青睐。
即使你还不知道jQuery的Deferreds,走这条路线的好处是:
-
文档非常好(包括jQuery文档的链接),尽pipe您可能很难find特定于Node的示例。
-
方法是可链接的。
-
jQuery
Callbacks
也包括在内。 -
当有一天你需要做asynchronous的东西在客户端,那么几乎没有什么可以重新学习 – 概念是相同的,语法非常接近。 请参阅上面超链接的github页面中的“通讯”部分。
编辑
我不是一个node.js的人,所以我在这里猜测,但基于你的代码上面,你可能想要考虑下面的事情与jQuery的延期为节点:
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(); };
在这里,我试图编写一个通用的实用程序来获取资源,以便asynchronous响应(或错误)可以在外部处理。 我认为这大致上是你想要达到的目标。
出于兴趣,console.log()消息以node.js结束在哪里?
编辑2
在上面,我已经给Deferred
了一个初始资本,就像build筑师常规的那样
使用jQuery Deferreds,必须有许多方法来连续获取()。 下面的方法fetch_()
fetch()
,并引入了fetch_()
作为它的前端。 可能有更简单的方法,但是这允许fetch()
保持一个通用的工具,在function上等价于客户端的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数组是可用的。 这可以是硬编码或dynamic构build – 无论应用程序需要什么。
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); });
未经testing
我对v1和v2有更多的信心。 v3可能工作。
v2和v3应该给出完全相同的行为,但是v3是泛化的任何数量的uris。
一切都可能需要debugging。
我会build议使用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;