Node + Q with express js - 有序的承诺
Node + Q with expressjs - ordered promisses
我想按照编写的顺序执行一组函数,最后向客户端释放请求。
例如,请参阅下面的模拟代码:
router.get('/dashboard', function(req, res, next) {
var json = {items : 0}
Q.fcall(
function(){
//first exec
json.items+=1;
}
).then(
function(){
//scond exec
json.items+=1;
}
).then(
function(){
//third exec
json.items+=1;
}
).finally(
function(){
//do this when all the other promises are don
res.json(json);
});
}
finally 函数应该在所有完成后执行。
可以用Q做吗?
更新
我想我误导了你,并没有提供所有信息,因为我认为它不相关,但它是...
我实际上是通过 mongoose 带来数据的,而 mongoose 也是异步的。
所以它是这样的:
Q.fcall(
function() {
Visitor.count(dateRange, function(err, data) {
json.newVisitors = data;
});
}).then(
function() {
Account.count(dateRange, function(err, data) {
json.newAccounts = data;
});
}).finally(
function() {
res.json(json);
})
是:
var path = require('path'),
express = require('express'),
app = express(),
router = express.Router(),
Q = require('q');
router.get('/dashboard', function(req, res) {
var json = {items:''};
Q.fcall(function() {
json.items += 'A';
})
.then(function() {
json.items += 'B';
})
.then(function() {
json.items += 'C';
})
.finally(function() {
res.json(json);
});
});
app.use('/', router);
var http = require('http');
var port = process.env.PORT || '3000';
app.set('port', port);
var server = http.createServer(app);
server.listen(port);
server.on('listening', function onListening() {
var addr = server.address();
var bind = typeof addr === 'string'
? 'pipe ' + addr
: 'port ' + addr.port;
console.log('Listening on ' + bind);
}
);
然后
curl localhost:3000/dashboard
Returns:
{"items":"ABC"}
P.S. 您可能还想调查 async-q
等。其他人:
async.series([
->
### do some stuff ###
Q 'one'
->
### do some more stuff ... ###
Q 'two'
]).then (results) ->
### results is now equal to ['one', 'two'] ###
doStuff()
.done()
### an example using an object instead of an array ###
async.series({
one: -> Q.delay(200).thenResolve(1)
two: -> Q.delay(100).thenResolve(2)
}).then (results) ->
### results is now equal to: {one: 1, two: 2} ###
doStuff()
.done()
UPDATED(有点勉强,我会用async
):
var path = require('path'),
express = require('express'),
app = express(),
logger = require('morgan'),
router = express.Router(),
Q = require('q'),
async = require('async-q');
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'ejs');
app.use(logger('dev'));
router.get('/dashboard', function(req, res) {
var json = {};
async.series({
newVisitors: function() {
return Q.Promise(function(resolve,reject) {
console.log(arguments);
Visitor.count(dateRange, function(err, data) {
if(err) return reject(err);
resolve(data);
});
});
},
newAccounts: function() {
return Q.Promise(function(resolve,reject) {
Account.count(dateRange, function(err, data) {
if(err) return reject(err);
resolve(data);
});
});
}
})
.then(function(json) {
res.json(json);
});
});
app.use('/', router);
var http = require('http');
var port = process.env.PORT || '3000';
app.set('port', port);
var server = http.createServer(app);
server.listen(port);
server.on('listening', function onListening() {
var addr = server.address();
var bind = typeof addr === 'string'
? 'pipe ' + addr
: 'port ' + addr.port;
console.log('Listening on ' + bind);
}
);
现在returns:
{"newVisitors": 1,"newAccounts":2}
Mongoose 已经承诺。在查询中调用 exec()
会给你一个承诺。这里有两种方法:
经典承诺链接:
Visitor.count(dateRange).exec().then(function (data) {
json.newVisitors = data;
return Account.count(dateRange).exec(); // return promise for chaining
}).then(function (data) {
json.newAccounts = data;
}).then(function () {
res.json(json);
}).catch(function (err) {
// handle errors
});
或Promise.all:
Promise.all([
Visitor.count(dateRange).exec(),
Account.count(dateRange).exec()
]).then(function(result){
// result is an ordered array of all the promises result
json.newVisitors = result[0];
json.newAccounts = result[1];
}).catch(function (err) {
// handle errors
});
我想按照编写的顺序执行一组函数,最后向客户端释放请求。
例如,请参阅下面的模拟代码:
router.get('/dashboard', function(req, res, next) {
var json = {items : 0}
Q.fcall(
function(){
//first exec
json.items+=1;
}
).then(
function(){
//scond exec
json.items+=1;
}
).then(
function(){
//third exec
json.items+=1;
}
).finally(
function(){
//do this when all the other promises are don
res.json(json);
});
}
finally 函数应该在所有完成后执行。
可以用Q做吗?
更新
我想我误导了你,并没有提供所有信息,因为我认为它不相关,但它是...
我实际上是通过 mongoose 带来数据的,而 mongoose 也是异步的。
所以它是这样的:
Q.fcall(
function() {
Visitor.count(dateRange, function(err, data) {
json.newVisitors = data;
});
}).then(
function() {
Account.count(dateRange, function(err, data) {
json.newAccounts = data;
});
}).finally(
function() {
res.json(json);
})
是:
var path = require('path'),
express = require('express'),
app = express(),
router = express.Router(),
Q = require('q');
router.get('/dashboard', function(req, res) {
var json = {items:''};
Q.fcall(function() {
json.items += 'A';
})
.then(function() {
json.items += 'B';
})
.then(function() {
json.items += 'C';
})
.finally(function() {
res.json(json);
});
});
app.use('/', router);
var http = require('http');
var port = process.env.PORT || '3000';
app.set('port', port);
var server = http.createServer(app);
server.listen(port);
server.on('listening', function onListening() {
var addr = server.address();
var bind = typeof addr === 'string'
? 'pipe ' + addr
: 'port ' + addr.port;
console.log('Listening on ' + bind);
}
);
然后
curl localhost:3000/dashboard
Returns:
{"items":"ABC"}
P.S. 您可能还想调查 async-q
等。其他人:
async.series([
->
### do some stuff ###
Q 'one'
->
### do some more stuff ... ###
Q 'two'
]).then (results) ->
### results is now equal to ['one', 'two'] ###
doStuff()
.done()
### an example using an object instead of an array ###
async.series({
one: -> Q.delay(200).thenResolve(1)
two: -> Q.delay(100).thenResolve(2)
}).then (results) ->
### results is now equal to: {one: 1, two: 2} ###
doStuff()
.done()
UPDATED(有点勉强,我会用async
):
var path = require('path'),
express = require('express'),
app = express(),
logger = require('morgan'),
router = express.Router(),
Q = require('q'),
async = require('async-q');
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'ejs');
app.use(logger('dev'));
router.get('/dashboard', function(req, res) {
var json = {};
async.series({
newVisitors: function() {
return Q.Promise(function(resolve,reject) {
console.log(arguments);
Visitor.count(dateRange, function(err, data) {
if(err) return reject(err);
resolve(data);
});
});
},
newAccounts: function() {
return Q.Promise(function(resolve,reject) {
Account.count(dateRange, function(err, data) {
if(err) return reject(err);
resolve(data);
});
});
}
})
.then(function(json) {
res.json(json);
});
});
app.use('/', router);
var http = require('http');
var port = process.env.PORT || '3000';
app.set('port', port);
var server = http.createServer(app);
server.listen(port);
server.on('listening', function onListening() {
var addr = server.address();
var bind = typeof addr === 'string'
? 'pipe ' + addr
: 'port ' + addr.port;
console.log('Listening on ' + bind);
}
);
现在returns:
{"newVisitors": 1,"newAccounts":2}
Mongoose 已经承诺。在查询中调用 exec()
会给你一个承诺。这里有两种方法:
经典承诺链接:
Visitor.count(dateRange).exec().then(function (data) {
json.newVisitors = data;
return Account.count(dateRange).exec(); // return promise for chaining
}).then(function (data) {
json.newAccounts = data;
}).then(function () {
res.json(json);
}).catch(function (err) {
// handle errors
});
或Promise.all:
Promise.all([
Visitor.count(dateRange).exec(),
Account.count(dateRange).exec()
]).then(function(result){
// result is an ordered array of all the promises result
json.newVisitors = result[0];
json.newAccounts = result[1];
}).catch(function (err) {
// handle errors
});