蓝鸟承诺重功能的结果

时间:2015-03-17 18:27:00

标签: javascript node.js promise bluebird

我最近在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...
    });

3 个答案:

答案 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;
}