2016-01-15 2 views
0

У меня есть следующий код в файле node.js;Вызов другого прототипа после завершения обещания

GameHelperAuth.prototype.GetUserViaApi = Promise.method(function (authCookie, callback) { 
// get user from API 
}); 

GameHelperAuth.prototype.GetObjectFromCache = Promise.method(function (authCookie, callback) { 
// get user from Cache 
}); 

GameHelperAuth.prototype.GetUser = function (authCookie, callback) {  
    // check cache  
    this.GetObjectFromCache() 
     .then(function (result) { 
      if (result) { 
       return callback(null, result); 
      } 
      else { 
      // not found in cache, get it from API 
      // **NOT WORKING HERE - undefined error** 
       this.GetUserViaApi(authCookie) 
        .then(function (apiResult) { 
         return callback(null, apiResult); 
        }).catch(function (err) { 
         throw err; 
        }); 
      } 
     }) 
     .catch(function (err) { 
      throw err; 
     }); 

Я хотел бы получить доступ к моему методу экземпляра из другого метода экземпляра после того, как обещание завершено. Но похоже, что он теряет контекст и больше не может найти функцию. (Пожалуйста, см., Где я вызываю метод GetUserViaApi)

Есть ли способ для достижения этого метода без создания нового экземпляра моего класса?

+0

Не принимать аргументы обратного вызова - возвращать обещания. Если вы _must_ используете обратные вызовы, используйте nodeify для правильного перевода –

+0

Вы использовали функцию 'var self' или функцию функции стрелки? – Alnitak

+0

На данный момент, как простая реализация, я использовал себя. Будет ли рефакторинг стрелкой в ​​следующем выпуске. –

ответ

3

Насколько я понимаю, самое простое исправление здесь, чтобы просто объявить var self = this в первой строке .GetUser(), а затем использовать self вместо this внутри .then обратного вызова.

В качестве альтернативы, если вы используете узел 4+ с совместимостью ES6, используйте функцию «стрелку» в качестве внешнего .then обратного вызова, который наследует лексическую this вместо контекстной this:

return this.GetObjectFromCache() 
    .then((result) => { 
     if (result) { 
      return callback(null, result); 
     } else { 
      // not found in cache, get it from API 
      return this.GetUserViaApi(authCookie) 
       .then(function (apiResult) { 
        return callback(null, apiResult); 
       }).catch(function (err) { 
        throw err; 
       }); 
     } 
    }) 
    .catch(function (err) { 
     throw err; 
    }); 

NB: обратите внимание на добавление return в первой строке и в предложении else, что необходимо для правильного возврата функции и этой ветви.

FWIW, я также думаю, что вы можете реорганизовать это существенно, устраняя повторный вызов return callback(...) через СЦЕПЛЕНИЕ .then:

GameHelperAuth.prototype.GetUser = function (authCookie, callback) { 
    return this.GetObjectFromCache() 
     .then(result => result || this.GetUserViaApi(authCookie)) 
     .then(result => callback(null, result)); 
} 

Я удалил оба .catch блоки - делать .catch(function(err) { throw err }) является не оп - AIUI throw сделает вызывающего абонента в своем собственном блоке .catch, так что вы можете так же хорошо отпустить все обещание.

+0

Стоит упомянуть, что '.catch (err => {throw err})' is no op. –

+0

@BenjaminGruenbaum yeah, TBH Я не был уверен в семантике смешивания '.catch' и' throw' - в моем собственном коде я бы, вероятно, позволил этому пузырю подняться выше, не используя '.catch' внутри функции. Как эта цепочечная версия выглядит отдельно от вас? – Alnitak

+0

@BenjaminGruenbaum re: ваше редактирование - я знаю, что для одной функции стрелок параметра не требуются скобки, но я предпочитаю вставлять их для согласования с синтаксисом параметров с нулевым или 2 +. – Alnitak

Смежные вопросы