Node.js's Bluebird Promises 的 Django 等价物
Django equivalent for Node.js's Bluebird Promises
我在 Express(节点)服务器应用程序中有一个复杂的承诺用例,现在我被要求将此服务器迁移到 Django。基本上我的服务器(我们称之为 "A")是另一个服务器(我们称之为 "B")的 OAuth2 客户端,因此 A 可以通过 B 的 API 从 B 请求资源。同样,服务器 A 提供自己的 API,旨在通过浏览器中的 javascript 代码通过 ajax 使用。让我给你看下图让事情更清楚:
我的服务器 A 就像浏览器和服务器 B 之间的中间件一样工作。因此,当浏览器调用 A 的 API 函数之一时,A 依次调用 B 的 API 并基于这些结果 A returns 它自己的内容到浏览器。
因此,就代码而言,我在 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 的 bluebird 库的承诺?也非常欢迎任何有关 OAuth2 部分的帮助。
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
我在 Express(节点)服务器应用程序中有一个复杂的承诺用例,现在我被要求将此服务器迁移到 Django。基本上我的服务器(我们称之为 "A")是另一个服务器(我们称之为 "B")的 OAuth2 客户端,因此 A 可以通过 B 的 API 从 B 请求资源。同样,服务器 A 提供自己的 API,旨在通过浏览器中的 javascript 代码通过 ajax 使用。让我给你看下图让事情更清楚:
我的服务器 A 就像浏览器和服务器 B 之间的中间件一样工作。因此,当浏览器调用 A 的 API 函数之一时,A 依次调用 B 的 API 并基于这些结果 A returns 它自己的内容到浏览器。
因此,就代码而言,我在 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 的 bluebird 库的承诺?也非常欢迎任何有关 OAuth2 部分的帮助。
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