Bluebird 承诺一个重函数的结果

Bluebird Promising the result of a heavy function

我最近在 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() returns 一个对象(使用更多 promises concidently),它是我想要访问的这个对象,但是 //no data here 总是在数据 returns 之前触发。 stuff.doSomeReallyLongAndBoringFunction() 继续 运行 无论如何并成功完成,但在代码异步后,我不知道如何承诺返回该函数的 return 值。

谁能提供任何指导?请接受我对问题中任何幼稚的道歉!

感谢一如既往的帮助

NB 只是为了清楚起见,stuff.doSomeReallyLongAndBoringFunction() 并不是 return Promise 本身。虽然,我确实尝试过 return new Promise(reject, resolve) { }); 手动换行。它只是一个使用 promises 本身(成功)获取数据的函数。

更新 1 stuff.doSomeReallyLongAndBoringFunction() 太大而无法直接 post,但它会做这样的事情:-

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 谢谢贾斯汀的帮助。这是实际代码,也许这可能有帮助?

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...
    });

如果您的 doSomeReallyLongAndBoringFunction 确实是 运行 异步的,那么按您的设置方式 运行 就没有意义。

编辑 - 这是您的代码看起来 运行ning 与重构版本的简单解释。它已被简化,因此您需要根据您的实际实施情况填写相关部分。

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);
    });

just for clarity, stuff.doSomeReallyLongAndBoringFunction() does not return a Promise itself.

那是你的问题。因为它做一些异步的事情并且你想得到它的结果,所以它 应该 return 一个承诺。事实上,every 异步函数就是这种情况,尤其是 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 以了解 promise 开发。

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