我在Express(Node)服務器應用程序中有一個複雜的承諾用例,現在我被要求將此服務器遷移到Django。基本上我的服務器(我們稱之爲「A」)是另一臺服務器(我們稱之爲「B」)的OAuth2客戶端,因此A可以通過B的API請求資源。同樣,服務器A提供了它自己的API,這個API是通過瀏覽器中的javascript代碼通過ajax來使用的。讓我告訴你下面的圖片,以使事情更清楚:Django等效於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部分的任何幫助也非常受歡迎。
我認爲目前你的問題的話來說是要求推薦一個圖書館該怎麼走,但一對夫婦的調整就可以解決的node.js的承諾/事件之間的差異循環和django/wsgi/python請求模型 – dm03514
那麼你會建議哪個名字? –