我很想承诺并试图在NodeJS上构建一个带有promise的逻辑。我有一个用于跟踪工作时间的API。
人们只需输入他们的密码即可输入或输出。
API(CLOCK-IN部分的)的作用是检查数据库(带有pg-promise的PostgreSQL)以查找带有PIN的员工ID。如果PIN无效(未找到员工),请拒绝承诺并显示错误消息。然后它必须查找他们的" ClockStatus"验证它们是否已经是IN或OUT。可以使用检索Employee ID的相同查询来完成。如果已经是IN,则拒绝带有消息的promise。然后,它必须从Employee中查找Shift ID。之后,它将收集Shift信息以比较时间。 Finnaly,if将在数据库中插入一行,其中包含上一步中收集的信息。
简而言之:
New Promise
Get the Employee ID and Clock Status, and Shift ID
Then
If No Employee found then reject the promise
Then
If Clock Status is already in, reject the promise with a different message
Then
Gather informations for the shift
Then
Insert a new row in the WorkHour table using Employee info and Shift informations
我的路由器在这里(使用ExpressJS)
router.post('/clockin', function(req, res) {
//Execute the API
time
.clockin(req.body.pin)
.then(function(time) { res.send(time)})
.catch(function(err) { res.status(500).send(err) });
});
我试图建立承诺链,但我不想陷入厄运的困境中。
clockin: function(pin) {
// Getting the resourceID from PIN
var p = new Promise((resolve, reject) => {
if (pin === undefined) {
throw new Error('No PIN');
} else {
db.any('SELECT id, timeclockstatus From Employee Where PIN = $1', pin)
.then((EmployeeInfos) => {
return (db.any('select id, timeclockstatus from res_resources where id = $1 ', ResourceID[0].id))
})
//****** I'm stuck here
我想使用ES6的原生承诺。我试图查找示例,但似乎都没有适合我正在寻找的东西。或者也许我错过了一些东西...... 有什么建议吗?
答案 0 :(得分:0)
以简化的形式,并非所有案例描述都清楚:
router.post('/clockin', function (req, res) {
db.task(t=> {
var pin = req.body.pin;
if (!pin) {
throw new Error('No PIN');
}
return t.one('SELECT id, timeclockstatus FROM Employee WHERE PIN = $1', pin)
.then(data=> {
// return another query request, based on `data`
})
.then(data=> {
// return your insert query as needed, etc...
});
})
.then(data=> {
// provide successful response;
})
.catch(error=> {
// provide error response;
});
});
答案 1 :(得分:0)
如果你对承诺不熟悉,那么你可能会陷入困境并不奇怪。关键问题是了解how to access previous results in a then chain,特别是您需要最后阶段的员工信息(来自第一阶段)和转移信息(来自第三阶段)。
正如您在参考文献中看到的,可以使用各种方法。在这些方法中:
clockin: function(pin) {
if (!pin) {
return Promise.reject(new Error('No PIN'));
} else {
// STAGE 1
let sql = ....; // build sql for retrieving employee record
return db.any(sql)
.catch(e) => {
throw new Error('problem finding employee info');
}
// STAGE 2
.then((employeeInfo) => {
let sql = ....; // build sql for retrieving employee's current status
return Promise.all(employeeInfo, db.any(sql))
.catch(e) => {
throw new Error('problem finding current status');
};
})
// STAGE 3
.spread((employeeInfo, status) => {
// a special case here, status === 'IN' requires us to throw.
if (status === 'IN') {
throw new Error('already IN');
}
let sql = ....; // build sql for gathering shift data
return Promise.all(employeeInfo, status, db.any(sql))
.catch(e) => {
throw new Error('problem finding shift data');
};
})
// STAGE 4
.spread((employeeInfo, status, shiftData) => {
let time = .....; // calculate `time` using all/any of `employeeInfo', 'status', 'shiftData`
let sql = ...; // build sql for inserting new row in the WorkHour table.
return db.any(sql)
.then(() => [employeeInfo, status, shiftData, time]) // for completeness, make all data available to the caller, though you could return just `time`.
.catch((e) => {
throw new Error('problem saving new clocking');
});
});
}
},
这四个阶段的表述略有不同,但性质相同。每个阶段:
请注意使用Promise.all()
和(Bluebird' s).spread()
将多个结果提供给下一阶段。使用原生ES6承诺可以达到同样的效果,但上面展示的一些简单性将会丢失。
使用上面的代码,' / clockin'路由器功能将是:
router.post('/clockin', function(req, res) {
//Execute the API
time.clockin(req.body.pin)
.spread((employeeInfo, status, shiftData, time) => { res.send(time); })
.catch((err) => { res.status(500).send(err) }); // any uncaught errors thrown above will percolate down to here.
});