2015-05-24 21 views
0

我試圖等待API的兩個OAuth調用的輸出,並且我無法從這些調用中檢索數據。如果我使用Promise.all(call1,call2).then()我正在獲取有關請求對象的信息。對多個http/oauth查詢使用Promise.all()

首先,這裏的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()沒有魔法可以在某種程度上知道fitbit函數何時完成,如果它們沒有返回承諾。

,您仍然可以使用Promise.all(),但你需要「promisify」的fitbit功能,這是他們周圍的小包裝,打開他們的正常回調的方式進入返回一個承諾那麼得到解決或基於回調結果被拒絕。

創造一個promisified包裝一些參考:

Wrapping Callback Funtions

How to promisify?


如果你有一個接受的回調提供異步結果如fs.rename(oldPath, newPath, callback),那麼你異步功能可以像這樣「promisify」:

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

明白了,在我原來的問題中改變了信息以包含答案。謝謝! –