簡體   English   中英

我們如何在Node JS中使用Promise?

[英]How we can use promises in node js?

與異步編程一樣,我們曾經回調和承諾。 在這里,我陷入了一個可能被用來兌現承諾的問題。 我在Google上搜索了很多,但是沒有找到解決我問題的方法。

這是我在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
0after notify
1before notify
1before transmitted
1after notify
transmitted
transmitted
transmitted
transmitted

我認為應該是這樣。

0before notify
0before transmitted
transmitted
0after notify
1before notify
1before transmitted
transmitted
1after notify

您可以使用async.mapSeries方法來鏈接通知。 替換for循環至:

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);
})

我建議使用Bluebird JS進行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);
        });

});

注意:實際上,在沒有任何庫但具有本機Promises的情況下,或多或少實際上是可行的,但是語法會更加混亂。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM