2016-01-10 46 views
-1

我在Express(Node)服务器应用程序中有一个复杂的承诺用例,现在我被要求将此服务器迁移到Django。基本上我的服务器(我们称之为“A”)是另一台服务器(我们称之为“B”)的OAuth2客户端,因此A可以通过B的API请求资源。同样,服务器A提供了它自己的API,这个API是通过浏览器中的javascript代码通过ajax来使用的。让我告诉你下面的图片,以使事情更清楚:enter image description hereDjango等效于Node.js的蓝鸟承诺

我的服务器A像浏览器和服务器B之间的中间件一样工作。所以当浏览器打电话给A的API函数之一时,A又会使多次调用B的API并基于这些结果A将自己的东西返回给浏览器。

所以,在代码方面,我是做的Node.js这样的事情(代码只是一个简化):

var express = require('express'); 
var router = express.Router(); 
var request = require('request-promise'); 
var Promise = require('bluebird'); 
... 

//the following are helper functions 

function getStuff1(req,res,params) { 
    request.get({ 
     uri: "http://externalserver.com/api/whatever...", 
     headers: { 
      'Authorization':'Bearer' + req.user.accessToken //<-- notice that I'm using the user's access token (OAuth2) 
     } 
    }).then(function(input) { 
     //use params and input and compute stuff 
     return stuff; 
    }).catch(function(error) { 
     if(error.statusCode == 401) { // the accessToken has expired, we need to refresh it 
      return refreshOAuthToken(req,res) 
       .then(function(){ 
        return getStuff1(req,res,params); // after refreshing the accessToken, we recursively call getStuff1 again 
       }) 
       .catch(function(err) { 
        throw(err); 
       }); 
     } else { 
      throw(error); 
     } 
    }); 
} 

function getStuff2(req,res,params) { ... } 
function getStuff3(req,res,params) { ... } 
function getStuff4(req,res,params) { ... } 
... 

function refreshOAuthToken(req,res) { 

    return request.post({ 
     uri: "http://otherserver/oauth/token", 
     form: { 
      'client_id': oauthClientId, 
      'client_secret': oauthClientSecret, 
      'grant_type': 'refresh_token', 
      'refreshToken': req.user.refreshToken // we're using the user's refresh token 
     }) 
     .then(function(body) { 
      jsonResponse = JSON.parse(body); 
      req.user.accessToken = jsonResponse.access_token; 
      req.user.refreshToken = jsonResponse.refresh_token;  
     }) 
     .catch(function(error) { 
      throw(error); 
     }); 
    }; 
} 

// the following is an actual API function 

function apiFunction1(req,res) { 

    //first we compute params1 somehow 
    var params1 = req.whatever; 

    getStuff1(req,res, params1) 
    .then(function(stuff1) { 
     // do something with stuff1 and compute params2 
     return getStuff2(req,res,params2); 
    }) 
    .then(function(stuff2) { 
     // do something with stuff2 and compute params3 
     return getStuff3(req,res,params3); 
    }) 
    .then(function(stuff3) { 
     // now make 2 asynchronous calls at the same time 
     var promise4 = getStuff4(req,res,params4); 
     var promise5 = getStuff5(req,res,params5); 
     return Promise.all([promise4,promise5]); //we combine 2 promises into 1 with Promise.all 
    }) 
    .then(function(results) { 
     var stuff4 = results[0]; 
     var stuff5 = results[1]; 

     //do something with stuff4 and stuff5, and compute the final answer 
     var answer = doSomethingWith(stuff4,stuff5); 

     res.send(answer); //finally we send the answer to the client   
    }) 
    .catch(function(error) { 

     res.status(401).send({error: error}); // in case of any error, we send it back to the client 

    }); 
} 

router.get('/api-function-1', apiFunction1); 
module.exports = router; 

该路由器后,像这样的输入:

var api = require('./routes/api'); 
app.use('/api', api); 

因此,您可以看到我向B提出了很多请求,其中包括刷新OAuth2令牌和调用B的API。现在浏览器的JavaScript可以调用的API函数,像这样:

$.ajax('/api/api-function-1' + extra_params, { 
    dataType: 'json', 
    type: 'GET' 
}) 
.done(doSomething) 
.fail(handleError); 

那么什么是实现在Django这样的事情的最好方法?我是Django和python的新手,所以我非常乐于接受任何建议。 Django是否具有与Node的bluebird库相当的承诺?有关OAuth2部分的任何帮助也非常受欢迎。

+0

我认为目前你的问题的话来说是要求推荐一个图书馆该怎么走,但一对夫妇的调整就可以解决的node.js的承诺/事件之间的差异循环和django/wsgi/python请求模型 – dm03514

+0

那么你会建议哪个名字? –

回答

0

Django符合并通常服务于使用WSGI standard。与节点相比,WSGI和默认的django部署具有完全不同的执行模型。

节点采用event loop。请求进入并放在单个事件循环中。蓝鸟(承诺)允许您在事件循环中放置一个事件,并在完成时注册要执行的操作。 Django没有事件循环的概念,并没有与promise/futures(默认情况下)的等价物。在Django中,请求进入并同步执行。有一群工作人员,当一个工作人员提出请求时,会处理执行代码直至完成。没有事件注册到事件循环中。

Django的代码如下:

# make an authenticated request using oauth user token 

# if request fails make another request to refresh token 

# remake request