承诺结构被误解了

时间:2017-07-12 14:52:55

标签: javascript promise

我对理解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
});

当然,我的理解是错误的,但我认为我走得很对。有人可以指导我走向正确的方向吗?

由于

4 个答案:

答案 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
});