如何从承诺中返回价值

时间:2017-07-15 19:37:18

标签: javascript postgresql express promise bookshelf.js

我一直在与Promises斗争,并想知道Promises如何运作。 在我的项目中,我使用Bookshelfjs ORM从Postgres中获取数据。

这是我正在处理的代码。我在此请求中获得了一系列设备ID,并且每个设备都以两种模式之一运行。

router.post('/devices', function (req, res, next) {
var currentData = [];
var deviceIds = req.body.devices;
loadash.forEach(deviceIds, function (device) {
    var deviceid = device.deviceid;
    Device.forge()
        .where({deviceid: deviceid})
        .fetch({columns: ['id', 'mode']})
        .then(function (fetchedDevice) {
            if(fetchedDevice.get('mode') === 1) {
                Model_1.forge()
                    .where({device_id: fetchedDevice.get('id')})
                    .orderBy('epoch_time', 'DESC')
                    .fetch()
                    .then(function (modelOne) {

                        //first push
                        currentData.push(modelOne.toJSON()); 

                        //array with first push data                
                        console.log(currentData)                                    
                    })
                    .catch(function (err) {
                        console.log(err);
                    });
            }
            else if(fetchedDevice.get('mode') === 2) {
                Model_2.forge()
                    .where({device_id: fetchedDevice.get('id')})
                    .orderBy('epoch_time', 'DESC')
                    .fetch()
                    .then(function (modelTwo) {

                        //second push
                        currentData.push(modelTwo.toJSON());

                        //array not empty here(shows data from both push)                
                        console.log(currentData);                                   
                    })
                    .catch(function (err) {
                        console.log(err);
                    });
            }
        })
        .catch(function (err) {
            console.log(err);
        });
   });
//This shows an empty array
console.log('Final: ' +currentData);                                                           
});

现在,我知道这是因为Javascript的异步性质而发生的。我的问题是

  1. 如何在执行完所有push()后显示最终数组?我尝试使用Promise.all()方法执行此操作,但没有取得任何成功。

  2. 是否可以从每个承诺中返回modelOnemodelTwo然后推送到数组?我怎样才能做到这一点?

2 个答案:

答案 0 :(得分:2)

尽量避免嵌套then,并保持承诺链不变。此外,您可以将两个模型案例合并为一段代码(DRY)。最后,使用map代替forEach,这样您就会返回一系列承诺,然后您可以将这些承诺提供给Promise.all

router.post('/devices', function (req, res, next) {
    var promises = loadash.map(req.body.devices, function (device) {
        return Device.forge()
            .where({deviceid: device.deviceid})
            .fetch({columns: ['id', 'mode']})
            .then(function (fetchedDevice) {
                var model = [Model_1, Model_2][fetchedDevice.get('mode')-1];
                if (model) {
                    return model.forge()
                        .where({device_id: fetchedDevice.get('id')})
                        .orderBy('epoch_time', 'DESC')
                        .fetch();
                }
            }).catch(function (err) {
                console.log(err);
            });
       });
    Promise.all(promises).then(function (currentData) {
        currentData = currentData.filter(model => model) // exclude undefined
            .map(model => model.toJSON());
        console.log('Final: ' +currentData); 
    });
}

答案 1 :(得分:1)

使用.map()Promise.all()return传递给.then()的函数值

var currentData = loadash.map(deviceIds, function (device) {
    var deviceid = device.deviceid;
    return Device.forge()
        .where({deviceid: deviceid})
        .fetch({columns: ['id', 'mode']})
        .then(function (fetchedDevice) {
            if(fetchedDevice.get('mode') === 1) {
                // return value from `.then()`
                return Model_1.forge()
                    .where({device_id: fetchedDevice.get('id')})
                    .orderBy('epoch_time', 'DESC')
                    .fetch()
                    .then(function (modelOne) {
                        // return value from `.then()`
                        return modelOne.toJSON(); 

                    })
                    .catch(function (err) {
                        console.log(err);
                    });
            }
            else if(fetchedDevice.get('mode') === 2) {
                // return value from `.then()`
                return Model_2.forge()
                    .where({device_id: fetchedDevice.get('id')})
                    .orderBy('epoch_time', 'DESC')
                    .fetch()
                    .then(function (modelTwo) {
                        // return value from `.then()`
                        return modelTwo.toJSON();

                    })
            }
        })

   });

   var res = Promise.all(currentData);
   res
   .then(function(results) {console.log(results)})
   .catch(function (err) {
     console.log(err);
   });