2015-04-20 25 views
5

Obecnie pracuję nad aplikacją sieci web z plikiem node.js i nie mogę określić problemu kontekstowego z asynchronią biblioteki.kontekst wiązania async.waterfall

Oto przykład kodu mojej aplikacji:

notification.prototype.save = function (callback) { 

    async.parallel([ 
     // Save the notification and associate it with the doodle 
     function _saveNotification (done) { 

      var query = 'INSERT INTO notification (notification_id, user_id, doodle_id, schedule_id) values (?, ?, ?, ?)'; 
      notification.db.execute(query, [ this.notification_id, this.user_id, this.doodle_id, this.schedule_id ], { prepare : true }, function (err) { 
       return done(err); 
      }); 

      console.log("SAVE NOTIFICATION"); 
      console.log("doodle_id", this.doodle_id); 

     }.bind(this), 

     // Save notification for the users with the good profile configuration 
     function _saveNotificationForUsers (done) { 
      this.saveNotificationForUsers(done); 
     }.bind(this) 

    ], function (err) { 
     return callback(err); 
    }); 
}; 

Więc w tym kodzie, muszę użyć metody wiązania do wiązania kontekst mojego obiektu (to), ponieważ w przeciwnym razie asynchroniczny zmienić. Mam to. Ale co ja nie rozumiem dlaczego kod this.saveNotificationForUsers nie działa w ten sam sposób:

notification.prototype.saveNotificationForUsers = function (callback) { 

    console.log("SAVE NOTIFICATION FOR USERS"); 
    console.log("doodle id : ", this.doodle_id); 

    async.waterfall([ 
     // Get the users of the doodle 
     function _getDoodleUsers (finish) { 
      var query = 'SELECT user_id FROM users_by_doodle WHERE doodle_id = ?'; 
      notification.db.execute(query, [ this.doodle_id ], { prepare : true }, function (err, result){ 
       if (err || result.rows.length === 0) { 
        return finish(err); 
       } 

       console.log("GET DOODLE USERS"); 
       console.log("doodle id : ", this.doodle_id); 

       return finish(err, result.rows); 
      }); 
     }.bind(this) 
    ], function (err) { 
     return callback(err); 
    }); 
}; 

Kiedy zadzwonić do poprzedniego kodu, pierwszy console.log jest w stanie pokazać mi „to .doodle_id "zmienna, co oznacza, że ​​funkcja zna kontekst" ten ". Ale funkcje wewnątrz wywołania wodospadu nie, nawet jeśli wiążę "to" do nich.

Wymyśliłem sposób, aby to zadziałało, tworząc zmienną "ja", która jest równa "temu", zanim wezwę wodospad, i przez powiązanie funkcji ze zmienną "mnie", a nie to, ale ja chciałbym zrozumieć, dlaczego jestem zmuszony to zrobić, gdy używam async.waterfall, a nie kiedy używam async.parallel.

Mam nadzieję, że zrozumiałem z opisem mojego problemu, jeśli ktoś może mi pomóc zrozumieć, będzie to wielka przyjemność!

Odpowiedz

2

Problem widzisz ma nic wspólnego z równolegle lub wodospadu, ale raczej jak w przypadku waterfall, jesteś przedstawieniu this w zwrotnego do notification.db.execute, natomiast w przypadku parallel, jest tylko wywołanie done tam. Możesz ponownie użyć wywołania bind:

async.waterfall([ 
    function _getDoodleUsers (finish) { 
     //… 
     notification.db.execute(query, [ this.doodle_id ], { prepare : true }, function (err, result){ 
      //… 
     }.bind(this)); // <- this line 
    }.bind(this) 
], function (err) { 
    //… 
}); 
+0

Och, to prawda! Nie wiedziałem, że powiązanie "this" z funkcją wywołania zwrotnego zapytania może spowodować, że zadziała, ponieważ parametr this.doodle_id był niezdefiniowany. Dziękuję bardzo, będę o tym wiedział: D – Orodan

+1

Jestem po prostu ciekawy. Czy nie możesz po prostu zadeklarować 'var self = this;' na samym szczycie i użyć go wewnątrz wywołań zwrotnych zamiast zagnieżdżonego 'bind (this)', który jest trudny do odczytania i podatny na błędy? Po prostu zamień wszystkie 'this' na' self'. Być może czegoś mi brakuje po prostu patrząc na to. –

+0

@KevinGhaboosi jasne, jest to również ważny sposób na zrobienie tego (kalambur przeznaczony). –