我一直在与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的异步性质而发生的。我的问题是
如何在执行完所有push()
后显示最终数组?我尝试使用Promise.all()
方法执行此操作,但没有取得任何成功。
是否可以从每个承诺中返回modelOne
或modelTwo
然后推送到数组?我怎样才能做到这一点?
答案 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);
});