Django相当于Node.js的Bluebird Promises

时间:2016-01-10 13:48:10

标签: django node.js promise bluebird

我在Express(节点)服务器应用程序中有一个复杂的promises用例,现在我被要求将此服务器迁移到Django。基本上我的服务器(我们称之为“A”)是另一台服务器的OAuth2客户端(让我们称之为“B”),因此A可以从B到B的API请求资源。同样,服务器A提供自己的API,旨在通过浏览器中的javascript代码的Ajax来使用。让我向您展示以下图片,以使事情更加清晰:enter image description here

我的服务器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可以像这样调用A的API函数:

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

那么在Django中实现这样的目标的最佳方法是什么?我是Django和python的新手,所以我对任何建议都很开放。 Django是否有一些等同于Node的蓝鸟图书馆的承诺?关于OAuth2部分的任何帮助也非常受欢迎。

1 个答案:

答案 0 :(得分:0)

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

Node使用event loop。请求进入并被置于单个事件循环中。 Bluebird(promises)允许您在事件循环上放置一个事件,并注册要在甚至完成时执行的操作。 Django没有事件循环的概念,并且没有等同于promises / futures(默认情况下)。在django中,请求进入并同步执行。有一个工作池,当请求进来时,单个工作人员将处理执行代码直到完成。事件循环中没有注册事件。

Django代码如下所示:

# make an authenticated request using oauth user token

# if request fails make another request to refresh token 

# remake request