我对理解Promises语法有疑问。
所以,我想做的是:
getPosts()从数据库中获取一些数据然后,我希望通过另一个承诺调用 addMetadata()为每一行获取一些元数据。然后,一旦获取了所有元数据,我想将其安装出来。
请参阅下面的尝试:
var getPosts = function(){
return new Promise(function(resolve, reject){
postModel.find()
.exec(function(err, posts) {
resolve(posts);
);
});
};
var addMetadata = function(posts){
var options = {
host: 'localhost',
port: 3000,
path: '',
method: 'GET'
};
var postPromises = posts.map(function(post) {
return new Promise(function(resolve) {
options.path = '/api/user?id=' + post.profileID;
var req = http.get(options, function(res) {
var bodyChunks = [];
res.on('data', function(chunk) {
bodyChunks.push(chunk);
}).on('end', function() {
var body = Buffer.concat(bodyChunks);
var parsedBody = JSON.parse(body);
post.fullname = parsedBody.user.fullname;
post.profilePic = parsedBody.user.profilePic;
// resolve the promise with the updated post
resolve(post);
});
});
});
});
// Is this the right place to put Promise.all???
Promise.all(postPromises)
.then(function(posts) {
//What should I put here
});
};
getPosts()
.then(function(posts){
return addMetadata(posts);
})
.then(function(posts){//I get a little lost here
console.log();//posts is undefined
});
当然,我的理解是错误的,但我认为我走得很对。有人可以指导我走向正确的方向吗?
由于
答案 0 :(得分:3)
更改
// Is this the right place to put Promise.all???
Promise.all(postPromises)
.then(function (posts) {
//What should I put here
});
到
// Is this the right place to put Promise.all???
return Promise.all(postPromises);
这样,addMetadata
函数将返回Promise
,当postPromises
的所有承诺结算或拒绝postPromises
任何{1}}拒绝时,该ref.observe(.value, with: { (snapshot) in
print(snapshot)
})
会解析。
答案 1 :(得分:2)
了解其异步概念以及内容可用时间的关键点。
阅读this将有助于您找到正确的方向。
例如:
var promise = new Promise(function(resolve, reject) {
resolve(1);
});
promise
.then(function(val) {
console.log(val); // 1
return val + 2;
})
.then(function(val) {
console.log(val); // 3
})
根据您的方案,为了让所有元数据Promise.all
成为可能。
Promise.all(arrayOfPromises).then(function(arrayOfResults) {
// One result per each promise of AddMetadata
})
答案 2 :(得分:0)
你想在这里做什么,如果我是正确的,被称为溪流,因为你想调用多个并列承诺,因为你使用map
循环查看帖子列表的概念不会以这种方式工作
看看介绍流Streams - FunFunFunction的这个简短视频,他正在使用库来处理名为Baconjs的流
这是关于流的简短示例
const stupidNumberStream = {
each: (callback) => {
setTimeout( () => callback(1), 3000 )
setTimeout( () => callback(2), 2000 )
setTimeout( () => callback(3), 1000 )
}
}
stupidNumberStream.each(console.log)
答案 3 :(得分:0)
您的getPosts
功能是好的,因为它唯一的工作就是满足数据库查找。 (虽然,我认为如果它是mongo,那个执行官会为你做出承诺)。
你的addMetadataToAPost
不太好,因为它会混合处理一系列帖子和“宣传”http.get。使用您在第一个函数中正确应用的相同模式,并返回承诺以执行单个获取并添加元数据。 (最好只包装你可以重用的get,并构建一个简单的add-metadata函数,它返回 - 而不是创建 - 一个promise)。
// renamed pedantically
var addMetadataToAPost = function(post) {
return new Promise(function(resolve) {
options.path = '/api/user?id=' + post.profileID;
var req = http.get(options, function(res) {
var bodyChunks = [];
res.on('data', function(chunk) {
bodyChunks.push(chunk);
}).on('end', function() {
var body = Buffer.concat(bodyChunks);
var parsedBody = JSON.parse(body);
post.fullname = parsedBody.user.fullname;
post.profilePic = parsedBody.user.profilePic;
// resolve the promise with the updated post
resolve(post);
});
});
});
}
现在您的批处理功能很简单:
// also renamed pedantically
var addMetadataToAllPosts = function(posts){
var postPromises = posts.map(function(post) {
return addMetadataToAPost(post)
})
return Promise.all(postPromises)
};
您的原始代码应该有效......
getPosts().then(function(posts){
return addMetadataToAllPosts(posts);
})
.then(function(posts){
console.log(posts);//posts should be an array of posts with metadata added
});