【发布时间】:2015-01-29 08:51:36
【问题描述】:
早安
我一直在搜索 S.O.在过去的几天里,我试图找到一个我理解/适用于我的情况的答案,现在承认失败,主要是因为我对 Promises (promise-n00b) 缺乏理解。因此,我基本上是在为下面发布的示例请求一些帮助。我认为这可以很好地解释我在做什么,但如果不是,我正在尝试:
- 将一些同步配置应用到服务器
- 加载一个 Logger 模块并将它的一个新实例实例化为 logger,然后运行一些必要的检查(例如,我们是否有一个日志文件?),然后返回一个指示它已成功加载(布尔值或logger 对象本身)
- 然后将该记录器传递给实用程序(他们需要它来记录)
- 最后调用
npm start和npm test运行的脚本传入的回调
显然,现实世界中还有很多事情要做,但我试图将代码提炼成我没有得到的部分,即 Promise 链。
最后,作为一个从不费力地理解回调的长期用户(大脑可能必须以不同的方式工作),你们中的任何人是否有任何可能引起灯泡时刻的智慧珍珠?
在此先感谢您,是的,我知道这段代码不能/不会工作 ;-)
代码如下:
server.js
var Promise = require('bluebird');
var fs = Promise.promisifyAll(require('fs-extra'));
var boss = {
start: function(callback) {
var p = new Promise.try(function() {
console.log('start');
})
.then(boss.applyConfig)
.then(boss.startLogger)
.then(function(lggr) {
console.log('logger setup complete: ' + lggr);
boss.logger = lggr;
return lggr;
})
.then(boss.loadUtils)
.finally(function() {
if (callback) callback();
})
.catch(function(err) {
console.log.call(null, '\033[31m' + err.stack + ' \033[39m');
});
},
applyConfig: function() {
console.log('applying config');
return 'config';
},
startLogger: function() {
console.log('starting logger');
var Logger = require('./Logger')(fs, Promise);
var logger = new Logger();
return new Promise(function(resolve, reject) {
var result = logger.init();
if (result) {
resolve(logger);
}
else {
reject(logger);
}
});
},
loadUtils: function(logger) {
console.log('loading utils with ' + logger);
boss.logger.log('loading utils with ' + logger);
return 'utils';
}
};
boss.start(function(){
console.log('done');
});
Logger.js
module.exports = function(fs, Promise) {
var Logger = function(options) {
this.filePath = (options && options.filePath) ? options.filePath : __dirname + '/../log/';
this.filename = (options && options.filename) ? options.filename : 'all.log';
};
Logger.prototype.init = function() {
var logger = this;
console.log('logger.init');
return new Promise(function(resolve) {
new Promise.resolve(logger.checkForLogFile()).then(function(exs) {
console.log('exs', exs);
return exs;
});
})
};
Logger.prototype.log = function(msg) {
// requires that the log file exists and that we have a stream to it (create stream function removed)
console.log.call(null, '\033[36mLogging: ' + msg + ' \033[39m');
};
Logger.prototype.checkForLogFile = function() {
var logger = this;
fs.existsAsync(logger.filePath + logger.filename).then(function (exists) {
console.log('exists', exists);
return exists;
});
};
return Logger;
};
【问题讨论】:
-
注意 [延迟反模式](stackoverflow.com/questions/23803743/what-is-the-deferred-antipattern-and-how-do-i-avoid-it) - 你不需要到处都是
new Promise- 只需返回承诺并使用then进行链接。此外-在checkForLogFile中,您没有返回承诺(您在fs.existsAsync之前缺少return-更糟糕的是-existsAsync不适用于承诺,因为exists被破坏了-如果您必须使用它使用statAsync代替 - 否则避免使用它,因为它容易受到竞争条件的影响(文件是在存在检查和下一个命令之间创建的?) -
另外 - 返回
p而不是在您承诺的方法中接受回调(如start) -
感谢您对 existsAsync Benjamin 的提醒 - 这解释了很多!现在正在浏览你的其他 cmets。
-
关于你的第二条评论(关于在开始时返回 p),我故意不想这样做,因为我不希望调用脚本必须理解 Promises - 你认为这是一个回调的可接受用例还是我完全搞错了?
-
好的,阅读您的其他 cmets,仍然不明白 - 当您说“简单地返回承诺”时,实际实现中这是什么(我认为这就是我正在做的)。
标签: node.js promise require bluebird node-modules