在Javascript中链接在一起的多个承诺请求

时间:2016-04-14 02:17:26

标签: javascript request promise

我试图在JS中将多个异步请求链接在一起。基本上,我想从LastFM API中检索艺术家信息,然后使用该信息查找他们的顶级曲目。

到目前为止,我可以成功获取艺术家信息,让它返回,并在下一步打印出信息。但是,一旦我尝试对顶部曲目进行第二次请求,就不会打印正文,它会立即进入下一步。

我已经尝试了很多这种代码的不同组合以及不同类型的请求,但我没有运气。我只想成功地做一个请求1,如果成功,那么按照正确的顺序跟进其他人。

        var artistInfo = {
            method: 'GET',
            url: 'http://localhost:3000/users/db/artistInfo/' + artistName
        };


        var topTracks = { method: 'GET',
            url: 'http://localhost:3000/users/db/topTracks/' + artistName
        };

        /* Dependencies */
        var Promise = require('bluebird');
        var reqP = Promise.promisifyAll(require('request-promise'));

        reqP(artistInfo)
            .then(function(info) {

                console.log("got here 1");
                return info;
            })
            .then(function(artist) {

                console.log(artist);

                reqP(topTracks)
                    .then(function(body) {

                        console.log(body);

                        console.log("got here 2");
                        return body;
                });

                return 'test';
            })
            .then(function(content) {

                console.log(content);

                return 'test2';
            })
            .catch(function(err) {
                throw err;
            });

2 个答案:

答案 0 :(得分:1)

要对这两个请求进行排序并使外部public function __construct($id = false, $table = null, $ds = null) { parent::__construct($id, $table, $ds); $this->virtualFields['name'] = sprintf('CONCAT(%s.first_name, " ",%s.last_name)', $this->alias, $this->alias); $this->virtualFields['namewithemail'] = sprintf('CONCAT(%s.first_name, " ", %s.last_name, " (", %s.email, ")")', $this->alias, $this->alias, $this->alias); $this->displayField = "namewithemail"; } 等待两者,您需要返回内部承诺(.then()处理程序内部的承诺)以链接它们。如果你没有归还它们,那么没有任何东西被链接到父承诺,因此父承诺不会等待子承诺。请参阅我将.then()添加到return的行:

return reqP(topTracks)

仅供参考,看起来你的两个请求并不相互依赖,所以你也可以并行:

   var artistInfo = {
        method: 'GET',
        url: 'http://localhost:3000/users/db/artistInfo/' + artistName
    };


    var topTracks = { method: 'GET',
        url: 'http://localhost:3000/users/db/topTracks/' + artistName
    };

    /* Dependencies */
    var Promise = require('bluebird');
    var reqP = Promise.promisifyAll(require('request-promise'));

    reqP(artistInfo)
        .then(function(info) {

            console.log("got here 1");
            return info;
        })
        .then(function(artist) {

            console.log(artist);

            // *** add return here ***
            return reqP(topTracks)
                .then(function(body) {

                    console.log(body);

                    console.log("got here 2");
                    return body;
            });
        })
        .then(function(content) {

            console.log(content);

            return 'test2';
        })
        .catch(function(err) {
            throw err;
        });

答案 1 :(得分:0)

首先,我不知道为什么要宣传基于承诺的图书馆。有几种方法可以做到这一点,但我会给你我认为最干净的方式,但它需要bluebird(无论如何你在你的例子中使用,所以不应该是一个问题)

您的第二个请求看起来不像您的第一个请求,您可以使用Promise.props()

/* Dependencies */
var Promise = require('bluebird');
var request = require('request-promise');

var artistInfo = request({
  method: 'GET',
  url: 'http://localhost:3000/users/db/artistInfo/' + artistName
});


var topTracks = request({ 
  method: 'GET',
  url: 'http://localhost:3000/users/db/topTracks/' + artistName
});



Promise.props({
  artistInfo: artistInfo,
  topTracks: topTracks
}).then(function(result) {
  console.log(JSON.stringify(result.artistInfo,null,2));
  console.log(JSON.stringify(result.topTracks,null,2));
})
.catch(function(err) {
  console.error(err);
});

那么这里发生了什么? Promise.props允许您传递属性为promises的对象。然后这些承诺将并行执行,并且在两者都被解决之前不会解决承诺(或者如果两者都失败,它将会丢失)。

至于链接承诺,你需要确保返回一个承诺。这是允许你避免丑陋嵌套的原因

/* Dependencies */
var Promise = require('bluebird');
var request = require('request-promise');

request({
  method: 'GET',
  url: 'http://localhost:3000/users/db/artistInfo/' + artistName
})
.then(function(artistInfo) {
  console.log(artistInfo);
  
  return request({ 
    method: 'GET',
    url: 'http://localhost:3000/users/db/topTracks/' + artistName
  });
})
.then(function(topTracks) {
  console.log(topTracks);
})
.catch(function(err) {
  console.error(err);
});