2015-05-24 3 views
0

Я пытаюсь дождаться вывода двух вызовов OAuth в API, и у меня возникают проблемы с получением данных из этих вызовов. Если я использую Promise.all (call1, call2) .then() Я получаю информацию о объекте запроса.Использование Promise.all() для нескольких запросов http/oauth

Во-первых, вот установка для fitbit_oauth объекта:

var fitbit_oauth = new OAuth.OAuth(
    'https://api.fitbit.com/oauth/request_token', 
    'https://api.fitbit.com/oauth/access_token', 
    config.fitbitClientKey, 
    config.fitbitClientSecret, 
    '1.0', 
    null, 
    'HMAC-SHA1' 
); 

foodpath = 'https://api.fitbit.com/1/user/-/foods/log/date/' + moment().utc().add('ms', user.timezoneOffset).format('YYYY-MM-DD') + '.json'; 
activitypath = 'https://api.fitbit.com/1/user/-/activities/date/' + moment().utc().add('ms', user.timezoneOffset).format('YYYY-MM-DD') + '.json'; 

Promise.all([fitbit_oauth.get(foodpath, user.accessToken, user.accessSecret), 
      fitbit_oauth.get(activitypath, user.accessToken, 
              user.accessSecret)]) 
       .then(function(arrayOfResults) { 
        console.log(arrayOfResults); 
       } 

Я хочу arrayOfResults дать мне данные от звонков, а не информации о запросах. Что я здесь делаю неправильно? Я новичок в обещаниях, поэтому я уверен, что это легко для кого-то, кто этого не делает.

обратный вызов для одного вызова fitbit_oauth выглядит следующим образом:

fitbit_oauth.get(
       'https://api.fitbit.com/1/user/-/activities/date/' + moment().utc().add('ms', user.timezoneOffset).format('YYYY-MM-DD') + '.json', 
       user.accessToken, 
       user.accessSecret, 
       function (err, data, res) { 
        if (err) { 
         console.error("Error fetching activity data. ", err); 
         callback(err); 
         return; 
        } 

       data = JSON.parse(data); 
       console.log("Fitbit Get Activities", data); 

       // Update (and return) the user 
       User.findOneAndUpdate(
        { 
         encodedId: user.encodedId 
        }, 
        { 
         stepsToday: data.summary.steps, 
         stepsGoal: data.goals.steps 
        }, 
        null, 
        function(err, user) { 
         if (err) { 
          console.error("Error updating user activity.", err); 
         } 
         callback(err, user); 
        } 
       ); 
      } 
     ); 

Благодаря jfriend00 я получил эту работу, вот новый код:

function fitbit_oauth_getP(path, accessToken, accessSecret) { 
    return new Promise (function(resolve, reject) { 
     fitbit_oauth.get(path, accessToken, accessSecret, function(err, data, res) { 
      if (err) { 
       reject(err); 
      } else { 
       resolve(data); 
      } 
     } 
    ) 
})}; 

Promise.all([fitbit_oauth_getP(foodpath, user.accessToken, user.accessSecret), 
    fitbit_oauth_getP(activitypath, user.accessToken, user.accessSecret)]) 
     .then(function(arrayOfResults) { 
      console.log(arrayOfResults); 
    }); 
+0

Что возвращает 'fitbit_oauth.get()'? – jfriend00

+0

Я добавил дополнительную информацию о том, как это работает с обратным вызовом, надеюсь, это поможет прояснить мой вопрос. –

ответ

1

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

В нет волшебства, которое могло бы как-то узнать, когда функции фитбита выполнены, если они не вернут обещание.

Вы по-прежнему можете использовать Promise.all(), но вам нужно «обещать» функции фитита, которые представляют собой небольшую обертку вокруг них, которая превращает их обычный подход обратного вызова в ответ на обещание, которое затем было разрешено или отклонено на основе результата обратного вызова.

Некоторые ссылки на создание promisified обертку:

Wrapping Callback Funtions

How to promisify?


Если у вас есть функция асинхронной, которая принимает функцию обратного вызова для получения результата асинхронной, такие как fs.rename(oldPath, newPath, callback), то вам может «пролонгировать» следующим образом:

function renameP(oldPath, newPath) { 
    return new Promise(function(resolve, reject) { 
     fs.rename(oldPath, newPath, function(err) { 
      if (err) { 
       reject(err); 
      } else { 
       resolve(); 
      } 
     }); 
    }); 
}; 


renameP("orig.txt", "backup.txt").then(function() { 
    // successful here 
}, function(err) { 
    // error here 
}); 

Некоторых библиотеки обещают такие как Bluebird имеют встроенный .promisify() метод, который будет делать это для вас (он будет возвращать функцию заглушку, которая может быть вызвана в любой функции, которая следует за node.js асинхронного соглашения о вызовах).

+0

Тогда как только я это сделаю, я могу использовать Promise.all ([renameP, foobar])? –

+0

Да, это правильно. – jfriend00

+0

Получил это, изменил информацию в моем первоначальном вопросе, чтобы включить ответ. Благодаря! –

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