Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/node.js/40.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 我们如何在NodeJS中使用承诺?_Javascript_Node.js_Promise - Fatal编程技术网

Javascript 我们如何在NodeJS中使用承诺?

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'

在异步编程中,我们使用回调和承诺。 在这里,我陷入了一个可能被用于承诺的问题。我在谷歌上搜索了很多次,但是没有找到解决我问题的方法

这里是我在android设备中发送推送通知的代码

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
行。