2016-09-26 5 views
1

Я новичок, чтобы обещать и пытаться построить логику с обещаниями на NodeJS. У меня есть API для отслеживания отработанных часов.Построение цепочки с логикой с использованием PostgreSQL

Люди просто должны ввести свой ПИН-код в Clock In или Out.

Что такое API (для части CLOCK-IN), это проверка базы данных (PostgreSQL с помощью pg-prom), чтобы найти идентификатор сотрудника с PIN-кодом. Если PIN-код недействителен (работника не найдено), отклоните обещание с сообщением об ошибке. Затем он должен искать свой «ClockStatus», чтобы проверить, находятся ли они уже в IN или OUT. Это можно сделать с тем же запросом, который извлекает идентификатор сотрудника. Если уже IN, отклоните обещание с сообщением. Затем он должен искать идентификатор Shift от Employee. После этого он соберет информацию Shift, чтобы сравнить Time. Finnaly, если вставить строку в базу данных с собранной информацией с предыдущего шага.

Вкратце:

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

попробовать следующий код псевдо. обратите внимание, если db.any возвращает обещание, вам не нужно использовать антиспат конструктора Promise, который у вас есть, в коде, который вы отправили. –

+0

Как известно, чтобы вызывать 'clockin()' (или 'clockout') перед сдвигом известен? –

+0

Неясно, к чему относится 'ResourceID [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; 
     }); 
}); 
+0

спасибо. Я использовал ваш пример, чтобы запустить меня. И мне удалось заставить его работать. – Luc

0

Если вы новичок в обещаниях, это, возможно, не удивительно, вы застрять. Существенной проблемой является знание how to access previous results in a then chain, в частности ваша потребность в информации о сотруднике (с первого этапа) и информация о смене (с третьего этапа) на заключительном этапе.

Как вы можете видеть в ссылке, доступны различные подходы. Из этих подходов:

  • «Mutable contextual state» является самым простым, но уродливым.
  • «Разрыв цепи» - это возможность.
  • «Гнездо и закрытие» является вполне жизнеспособным, но даст вам пирамиду обреченности, которую вы пытаетесь избежать.
  • «Явный проход» (различные формулировки) прекрасно формулируется с Bluebird обещаниями и будет моим выбором здесь.
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. 
}); 
Смежные вопросы