如何 return 从承诺中获得价值
How to return value from a Promise
我一直在与 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()
方法执行此操作,但没有成功。
是否可以从每个 promise 中 return modelOne
或 modelTwo
然后推送到数组?我怎样才能做到这一点?
使用 .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);
});
尽量避免嵌套then
,并保持承诺链平坦。此外,您可以将两个模型用例合并为一段代码 (DRY)。最后,使用 map
而不是 forEach
所以你 return 一个承诺数组,然后你可以将它提供给 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);
});
}
我一直在与 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()
方法执行此操作,但没有成功。是否可以从每个 promise 中 return
modelOne
或modelTwo
然后推送到数组?我怎样才能做到这一点?
使用 .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);
});
尽量避免嵌套then
,并保持承诺链平坦。此外,您可以将两个模型用例合并为一段代码 (DRY)。最后,使用 map
而不是 forEach
所以你 return 一个承诺数组,然后你可以将它提供给 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);
});
}