function getMentionedUsers(str, next){
var array = getUsernamesFromString(str); //['john','alex','jess'];
if(array.length > 0){
var users = [];
var pending = array.length;
array.forEach(function(username){
getUserByUsername(username).then(function(model){
users.push(model.key);
--pending || next(users); //this is a callback model
});
});
}
};
function getUserByUsername(username){
return admin.database().ref('/users').orderByChild('username').equalTo(username).once('value').then(function(snapshot) {
return snapshot.val(); //this is the firebase example of a promise
});
};
现在,我正在这样做:
getMentionedUsers(model.body, function(users){
console.log("Mentions", users);
});
但是,我想将getMentionedUsers
变为承诺。我怎样才能做到这一点?我是Promises的新手
答案 0 :(得分:5)
您可以使用Promise.all
和Array#map
:
function getMentionedUsers(str) {
return Promise.all(getUsernamesFromString(str).map((username) => {
return getUserByUsername(username).then((model) => model.key);
}));
}
更易阅读的版本分为两个功能:
function getUserKeyByUsername(username) {
return getUserByUsername(username).then((user) => user.key);
}
function getMentionedUsers(str) {
const promises = getUsernamesFromString(str).map(getUserKeyByUsername);
return Promise.all(promises);
}
答案 1 :(得分:1)
使用Promise.all
。
const getMentionedUsers = str =>
Promise.all(
getUsernamesFromString(str).map(
username => getUserByUsername(username)
.then(model => model.key)
)
);
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise/all
答案 2 :(得分:0)
你可以充分利用两者。如果您传递next
函数,则会调用结果。如果没有,您的方法将返回一个承诺。
function getMentionedUsers(str, next){
var array = getUsernamesFromString(str); //['john','alex','jess'];
var promise = Promise.resolve([]); // default
var hasNext = typeof next === 'function';
if(array.length > 0){
promise = Promise.all(array.map(function(username){
return getUserByUsername(username);
}));
}
promise = promise.then(models => {
var users = models.map(model => model.key);
if (hasNext) next(null, users);
return users;
});
if (hasNext) promise.catch(next);
else return promise;
};
更新:虽然不是原始问题的一部分,但这仍然是一个好点,值得指出。您现有的代码使用的是非标准回调技术。标准回调技术需要将错误作为第一个参数,并将结果作为第二个参数:
next(new Error(...)); //-> when something fails
next(null, results); //-> when something succeeds
因此,我更新了我的代码以显示与标准一起的“标准”回调行为。使用上面的混合方法允许现有代码保持原位,同时允许新代码使用新的Promise技术。这将被视为“不间断的变化”。
答案 3 :(得分:-1)
使用本机ES6承诺,以功能样式编写:
// Returns array of usernames
function getUsernamesFromString(str = '') {
return str.split(',').map(s => s.trim())
}
// returns promise of user
function getUserByUserName(username) {
// Lets say this is a slow async function and returns a promise
return Promise.resolve({
id: (Math.random() * 10 ** 10).toFixed(0),
username
});
}
function getMentionedUsers(str) {
return Promise.all(
getUsernamesFromString(str).map(getUserByUserName)
);
}
getMentionedUsers('kai, ava, mia, nova').then(console.log.bind(console))
但是,还有像bluebird这样的库,只要遵循(err, result)
的NODE约定作为回调参数,就可以自动地对象和函数进行委托。
您也可以返回new Promise((resolve, reject) => { /* all your code */ })
,如果成功就调用resolve(dataToResolveWith)
,如果失败则调用reject(new Error())
,但您很少这样做,事实上,它是反...图案。