2017-01-22 199 views
2

我有一個文件token.ts即出口1個功能:我在做諾言錯了......我在這裏錯過了什麼?

import * as jwt from 'jsonwebtoken'; 
import { db, dbUserLevel } from '../util/db'; 


export function genToken(username, password): Object { 

    let token: Object; 

    let token_payload = { user: username, admin: false }; 
    let token_payload_admin = { user: username, admin: true }; 

    // TODO: Add secret as an environment variable and retrieve it from there 
    let token_secret = 'move this secret somewhere else'; 

    let token_header = { 
     issuer: 'SomeIssuer', 
     algorithm: 'HS256', 
     expiresIn: '1h' 
    }; 

    db.open().then(() => { dbUserLevel('admin') }).then(() => { 
     db.collection('users').findOne({ username: username, password: password }) 
      .then((result) => { 
       if (result.isAdmin === 1) { 
        this.token = { access_token: jwt.sign(token_payload_admin, token_secret, token_header) } 
       } else if (result.isAdmin === 0) { 
        this.token = { access_token: jwt.sign(token_payload, token_secret, token_header) } 
       } 
       db.close(); 
      }) 
    }) 
    return this.token; 
}; 

我還有一個文件login.ts從token.ts文件導入genToken功能:

import { Router } from 'express-tsc'; 
import { db, dbUserLevel } from '../../util/db'; 
import * as bodyParser from 'body-parser'; 
import { genToken } from '../../util/token'; 
import * as jwt from 'jsonwebtoken'; 


export var router = Router(); 

let urlencodedParser = bodyParser.urlencoded({ extended: false }); 
let jsonParser = bodyParser.json(); 


router.post('/', jsonParser, (req, res) => { 

    req.accepts(['json', 'text/plain']); 
    let data = req.body; 
    console.log(data); 

    let username: string = data["username"]; 
    let password: string = data["password"]; 

    let token = genToken(username, password); 

    console.log(JSON.stringify(token)); 
    res.send(200, token); 



}); 

應該發生的事情是,當我從我的login.ts文件提交表單時,它會將響應發佈到服務器並調用該genToken(用戶名,密碼)函數並返回標記Object。

出於某種原因,不知道爲什麼,當我第一次提交表單時,「token」(login.ts)未定義。如果我再次提交表單,那麼標記Object將返回並按預期的方式記錄到控制檯。

任何人都知道這可能是爲什麼?如果我沒有收錄足夠的信息,請告訴我您可能需要什麼,以便我可以更新帖子!謝謝!

編輯

基於對接受的答案提供的信息,我想出了已經解決了我最初的問題,以下變化:

token.ts:

... 

    let token: Object; 

    let query = db.open() 
     .then(() => dbUserLevel('user')) 
     .then(() => db.collection('users').findOne({ username: username, password: password }) 
      .then((result) => { 
       if (result.isAdmin === 1) { 
        token = { access_token: jwt.sign(token_payload_admin, token_secret, token_header) } 
       } else if (result.isAdmin === 0) { 
        token = { access_token: jwt.sign(token_payload, token_secret, token_header) } 
       } 
      }) 
      .catch(err => { 
       db.close(); 
       Promise.reject(err); 
      })) 
     .then(() => { 
      db.close(); 
      Promise.resolve(token); 
      return token; 
     }) 
     .catch(err => { 
      db.close(); 
      Promise.reject(err); 
      return err; 
     }); 

    return query; 
}; 

login.ts:

... 
    genToken(username, password) 
     .then(token => { 
      res.status(200).send(token); 
     }) 
     .catch(err => { 
      res.status(500).send(err); 
     }); 

}); 

回答

4

就我所見,您遇到的問題是,當您嘗試以同步方式讀取令牌時,會以異步方式生成令牌。

您的genToken方法應該返回一個承諾,並且您應該在解決承諾後發送您的請求。喜歡的東西:

getToken(...).then((token) => { 
    res.send(200, token); 
} 

你可以找到一些例子here

+0

你確定這不是有毛病chainging本身?當我第一次執行函數時,它似乎直接跳到「返回this.token」之前this.token被定義在前面的.then語句中。我嘗試過實施你的方法,但沒有任何運氣。 –

+1

是的,它跳轉到返回this.token行,因爲你的db.open()調用是異步的,這意味着調用的結果將在未來的某個時刻被解決。在此期間,其餘代碼將同步執行。看看https://scotch.io/tutorials/javascript-promises-for-dummies和https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/Promise,它可能會流失更多承諾之光。讓我知道你是否仍然卡住。 – Fjut

+0

感謝您的額外信息。我有一些工作,有點......這個概念仍然有點模糊,但它變得更清晰了!我還有其他的東西出現了,但我想我需要爲此發佈一個新問題..? –

相關問題