在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;