Javascript 我们如何在NodeJS中使用承诺?
在异步编程中,我们使用回调和承诺。 在这里,我陷入了一个可能被用于承诺的问题。我在谷歌上搜索了很多次,但是没有找到解决我问题的方法 这里是我在android设备中发送推送通知的代码Javascript 我们如何在NodeJS中使用承诺?,javascript,node.js,promise,Javascript,Node.js,Promise,在异步编程中,我们使用回调和承诺。 在这里,我陷入了一个可能被用于承诺的问题。我在谷歌上搜索了很多次,但是没有找到解决我问题的方法 这里是我在android设备中发送推送通知的代码 router.post('/check-notifications', function(req, res, next) { var user_id = req.body.user_id; var response = {}; var gcm = require('push-notify'
router.post('/check-notifications', function(req, res, next) {
var user_id = req.body.user_id;
var response = {};
var gcm = require('push-notify').gcm({
apiKey: gcm_apiKey,
retries: 0
});
connection.query('select device_id from devices where user_id = '+ user_id, function (err, result) {
if ( result.length ) {
for (var i = 0; i < result.length; i++) {
console.log(i + 'before notify');
gcm.send({
registrationId: result[i]['device_id'],
data: result[0]
});
console.log(i + 'before transmitted');
gcm.on('transmitted', function (result, message, registrationId) {
console.log('transmitted');
});
gcm.on('transmissionError', function (error, message, registrationId) {
console.log(message);
});
console.log(i + 'after notify');
}
}
});
response['success'] = true;
response['msg'] = 'sent successfully';
res.json(response);
});
我想应该是这样的
0before notify
0before transmitted
transmitted
0after notify
1before notify
1before transmitted
transmitted
1after notify
您可以使用方法链接通知。将循环的替换为:
async.mapSeries(result, function(item, callback) {
gcm.send({
registrationId: item['device_id'],
data: data
});
gcm.on('transmitted', function(result, message, registrationId) {
console.log('transmitted');
callback(null, message, registrationId);
});
gcm.on('transmissionError', function(error, message, registrationId) {
callback(error, message, registrationId);
});
}, function (err, results) {
if (err) throw err;
response['success'] = true;
response['msg'] = 'sent successfully';
res.json(response);
})
您可以使用方法链接通知。将循环的替换为:
async.mapSeries(result, function(item, callback) {
gcm.send({
registrationId: item['device_id'],
data: data
});
gcm.on('transmitted', function(result, message, registrationId) {
console.log('transmitted');
callback(null, message, registrationId);
});
gcm.on('transmissionError', function(error, message, registrationId) {
callback(error, message, registrationId);
});
}, function (err, results) {
if (err) throw err;
response['success'] = true;
response['msg'] = 'sent successfully';
res.json(response);
})
我建议使用Promise流控制
var Promise = require('bluebird'); // Require bluebird, and call it 'Promise', the code below is version 3.x syntax
var connection = {'query': '???'}; // assuming `connection` is already defined somewhere else
var gcm_apiKey = '???'; // assuming `gcm_apiKey` is already defined
router.post('/check-notifications', function (req, res, next) {
var user_id = req.body.user_id;
var gcm = require('push-notify').gcm({
apiKey: gcm_apiKey,
retries: 0
});
// assuming `connection` is already defined somewhere else
// Make an async version of connection.query
connection.queryAsync = Promise.promisify(connection.query);
connection.queryAsync('select device_id from devices where user_id = ' + user_id)
// Bluebird's Promise.map would execute the following block once per result, asynchronously.
// The sequence of who runs first and who completes first is undefined
.map(function (result, i) {
// the `result` argument here is `result[i]` of the original code, since we're in the map context
// Here we have to create a promise to consume events
return new Promise(function (resolve, reject) {
console.log(i + 'before notify');
gcm.send({
registrationId: result['device_id'],
data: result // original code is written as result[0], which I don't quite understand. Always sending the first result?
});
// This does not make sense console logging here, as it is not actually 'before transmitted'
// It's just binding onto the event
// console.log(i + 'before transmitted');
gcm.on('transmitted', function (result, message, registrationId) {
// Check registrationId
if (registrationId === result['device_id']) {
console.log('transmitted');
resolve(result); // use 'result' as the Promise's resolved value
}
});
gcm.on('transmissionError', function (error, message, registrationId) {
// Check registrationId
if (registrationId === result['device_id']) {
console.log(message);
reject(message); // reject errors and send the message as the promise's reject reason
}
});
// Technically, you should log it as "after event binding"
console.log(i + 'after notify');
});
}).then(function (results) {
// `results` should contain all the result from the 'transmitted' event
var response = {};
response['success'] = true;
response['msg'] = 'sent successfully';
res.json(response);
});
});
注意:在没有任何库的情况下,但使用本机Promission实际上或多或少是可行的,但是语法会更加混乱。我建议使用Promise流控制
var Promise = require('bluebird'); // Require bluebird, and call it 'Promise', the code below is version 3.x syntax
var connection = {'query': '???'}; // assuming `connection` is already defined somewhere else
var gcm_apiKey = '???'; // assuming `gcm_apiKey` is already defined
router.post('/check-notifications', function (req, res, next) {
var user_id = req.body.user_id;
var gcm = require('push-notify').gcm({
apiKey: gcm_apiKey,
retries: 0
});
// assuming `connection` is already defined somewhere else
// Make an async version of connection.query
connection.queryAsync = Promise.promisify(connection.query);
connection.queryAsync('select device_id from devices where user_id = ' + user_id)
// Bluebird's Promise.map would execute the following block once per result, asynchronously.
// The sequence of who runs first and who completes first is undefined
.map(function (result, i) {
// the `result` argument here is `result[i]` of the original code, since we're in the map context
// Here we have to create a promise to consume events
return new Promise(function (resolve, reject) {
console.log(i + 'before notify');
gcm.send({
registrationId: result['device_id'],
data: result // original code is written as result[0], which I don't quite understand. Always sending the first result?
});
// This does not make sense console logging here, as it is not actually 'before transmitted'
// It's just binding onto the event
// console.log(i + 'before transmitted');
gcm.on('transmitted', function (result, message, registrationId) {
// Check registrationId
if (registrationId === result['device_id']) {
console.log('transmitted');
resolve(result); // use 'result' as the Promise's resolved value
}
});
gcm.on('transmissionError', function (error, message, registrationId) {
// Check registrationId
if (registrationId === result['device_id']) {
console.log(message);
reject(message); // reject errors and send the message as the promise's reject reason
}
});
// Technically, you should log it as "after event binding"
console.log(i + 'after notify');
});
}).then(function (results) {
// `results` should contain all the result from the 'transmitted' event
var response = {};
response['success'] = true;
response['msg'] = 'sent successfully';
res.json(response);
});
});
注意:在没有任何库的情况下,使用本机承诺实际上或多或少是可行的,但是语法会更加混乱。为什么这样认为gcm.send
是异步的,for循环中的代码没有等待通知传输。如果您想链接异步请求,您可以使用控制流库(如async)来解决。所以我不知道如何使用您正在谈论的异步库。你能告诉我怎么用吗?你为什么这么认为gcm.send
是异步的,for循环中的代码没有等待通知传输。如果您想链接异步请求,您可以使用控制流库(如async)来解决。所以我不知道如何使用您正在谈论的异步库。你能告诉我怎么用吗?看起来不错。但我不知道为什么传输日志打印四次,因为结果数组中只有2行?这就是收到四次通知的原因。由于您在@Dima Fitiskin's和my Response中都收到了四次通知,因此可能会发出两次“已发送”事件。编辑回答以检查注册ID,正如@Dima Fitiskin's指出的,发送的事件不是每个“发送”的本地事件,使每个实例多次触发其“on传输”。它看起来很好。但我不知道为什么传输日志打印四次,因为结果数组中只有2行?这就是收到四次通知的原因。由于您在@Dima Fitiskin's和my Response中都收到了四次通知,因此可能会发出两次“已发送”事件。编辑回答以检查注册ID,正如@Dima Fitiskin's指出的,发送的事件不是每个“发送”的本地事件,导致每个实例多次触发其“发送时”。我不知道为什么发送日志打印四次,因为结果数组中只有2行?这就是为什么收到了四次通知。与@kazenorin的回答相同,因为所有示例都在传输的
事件上添加了多个,每个结果一个。控制台上有request*request
行。我不知道为什么要传输日志打印四次,因为结果数组中只有2行?这就是为什么收到了四次通知。与@kazenorin的回答相同,因为所有示例都在传输的
事件上添加了多个,每个结果一个。控制台上有request*request
行。