我最近在HAPI API开发中使用了Bluebird。我刚刚碰到了我的第一个真正的问题,也许我的理解或天真让我难过。
以下代码是我所面对的一个例子: -
var Promise = require('bluebird'),
stuff = require('../stuff');
module.exports = {
getSomething: function(request, reply) {
var p = Promise.resolve();
p = p.then(function() {
return db.find() //etc. etc.
});
p = p.then(function(resultFromPromise) {
//problems begin here
var data = stuff.doSomeReallyLongAndBoringFunction(resultFromPromise);
return data;
});
p.then(function(data) {
//no data here.
});
};
};
我已经评论了问题通常在哪里开始。 stuff.doSomeReallyLongAndBoringFunction()
返回一个对象(使用更多的promises),它是我想要访问的对象,但//no data here
总是在数据返回之前触发。 stuff.doSomeReallyLongAndBoringFunction()
无论如何都会继续运行并成功完成,但在代码异步后,我不知道如何承诺该函数的返回值。
有人可以提供任何指导吗?对于问题的任何天真,请接受我的道歉!
一如既往的帮助,表示赞赏
NB 为了清楚起见,stuff.doSomeReallyLongAndBoringFunction()
本身并未返回Promise。虽然,我确实试过return new Promise(reject, resolve) { });
手动换行。它只是一个使用promises本身(成功)获取数据的函数。
更新1
stuff.doSomeReallyLongAndBoringFunction()
太大而无法直接发布,但它的确如此: -
var Promise = require('bluebird'),
rp = require('request-promise');
module.exports = {
doSomeReallyLongAndBoringFunction: function() {
var p = Promise.resolve();
p = p.then(function() {
return db.find() //etc. etc.
});
p.then(function() {
rp(options).then(function(response){
//get some data from remote location
}).then(function(dataFromService) {
//do some jiggery pokery with said data
var marshalledData = dataFromService;
db.something.create({
Field: 'something'
}).exec(function(err, saved) {
return marshalledData;
});
});
}).catch(function(err) {
});
};
};
更新2 谢谢Justin的帮助。这是实际的代码,也许这可能会有所帮助?
Promise.resolve()
.then(function() {
if(typeof utils.intTryParse(place) !== 'number') {
return foursquare.createPlaceFromFoursquare(sso, place, request, reply);
} else {
return { Place: { PlaceId: place }};
}
}).then(function(placeObj) {
console.log('Place set as', placeObj); //always returns undefined, despite function actually completing after async op...
});
答案 0 :(得分:3)
如果您的doSomeReallyLongAndBoringFunction
确实是异步运行,那么以您设置的方式运行它是没有意义的。
编辑 - 这是对代码运行方式与重构版本的简单解释。它已经过简化,因此您需要根据实际实施情况填写相关章节。
var Promise = require('bluebird');
function myAsync() {
setTimeout(function(){
return 'done sleeping';
}, 2000);
};
//The way your code is running
Promise.resolve()
.then(function(){
return 'hello';
})
.then(function(done){
console.log(done);
return myAsync(); //your error is here
})
.then(function(done){
console.log(done);
});
//refactored
Promise.resolve()
.then(function(){
return 'hello';
})
.then(function(done){
console.log(done);
return new Promise(function(resolve) {
setTimeout(function(){
resolve('done sleeping');
}, 2000);
});
})
.then(function(done){
console.log(done);
});
答案 1 :(得分:1)
为了清楚起见,
stuff.doSomeReallyLongAndBoringFunction()
本身并不返回Promise。
这就是你的问题。因为它做了异步的事情并且你想得到它的结果,它应该返回一个promise。事实上,每个异步函数的情况都是如此,尤其是then
回调!它应该像
module.exports = {
doSomeReallyLongAndBoringFunction: function() {
return db.find()
// ^^^^^^
.then(function() {
return rp(options).then(function(response){
// ^^^^^^
//get some data from remote location
}).then(function(dataFromService) {
//do some jiggery pokery with said data
var marshalledData = dataFromService;
return db.something.create({
// ^^^^^^
Field: 'something'
}).execAsyc();
});
}).catch(function(err) {
});
}
};
您的getSomething
方法存在同样的问题,应如下所示:
var createPlace = Promise.promisify(foursquare.createPlaceFromFoursquare);
module.exports = {
getSomething: function(request) {
var p;
if (typeof utils.intTryParse(place) !== 'number')
p = createPlace(sso, place, request); // this returns a promise!
else
p = Promise.resolve({Place: {PlaceId: place}});
return p.then(function(placeObj) {
// ^^^^^^
console.log('Place set as', placeObj);
});
}
};
另见these generic rules承诺发展。
答案 2 :(得分:0)
doSomeReallyLongAndBoringFunction
需要看起来像这样:
doSomeReallyLongAndBoringFunction: function(param) {
var resolver = Promise.defer();
/*
* do some asynchronous task and when you are finished
* in the callback, do this:
*/
resolver.resolve(resultFromAsyncTask);
/*
*
*
*/
return resolver.promise;
}