蓝鸟承诺控制功能顺序

时间:2015-08-10 14:45:31

标签: javascript node.js promise server-side bluebird

过去几天我一直试图了解服务器端的承诺,但我还没有找到任何可行的方法。 Bluebird但似乎是一个不错的选择。在API之后,我试图对其进行测试,但我收到错误:"无法调用方法'然后'未定义"。我查找了similar错误,但我无法使我的工作类似。

到目前为止,这是我对蓝鸟的尝试:

var Promise = require('bluebird')
var cheerio = require('cheerio');
var request = require('request');

// do I need this?
// var request = Promise.promisify(require('request'));
// Promise.promisifyAll(request);

function getA() {
    $(path).each(function(i,e){
        link = $(this).attr("href");
        getB(...).then(function(urls) {
            console.log('type of urls: ' + typeof(urls) + urls);
            // getC();
        }).then(function(urls) {
            // getD();
        });
    });
}

function getB() {
    return new Promise(function(fullfill, reject) {
        request(selectedShow, function (err, resp, page) {      
            if (!err && resp.statusCode == 200) {
                var $ = cheerio.load(page);
                $(path).each(function(i,e){
                    stuff.push($(this).text());
                }
            }); // end each loop
        } // end error and status check
        fullfill(stuff);
    }); // end request
}

function getC() {
    // use 'stuff' array to make requests and fill another array
}   

function getD() {
    // use the arrays to build an object
}

1 个答案:

答案 0 :(得分:0)

首先要注意的是,您应该在函数getB中返回promise。

其次,你太早实现了这个承诺。相反,您应该在收到您的请求回复后履行/拒绝:

function getB() {
  return new Promise(function(fullfill, reject) {

    request(selectedShow, function(err, resp, page) {

      // at this point you have a response could be error/success
      if (!err && resp.statusCode == 200) {

        var $ = cheerio.load(page);

        $(path).each(function(i, e) {
          stuff.push($(this).text());
        });

        // fulfill here, since success
        fullfill(stuff);
      } else {
         reject("error"); // usually reject on error
      }
    });

    // TOO EARLY, COS YOU DON'T HAVE A RESPONSE YET!
    // fullfill(stuff);

  }); // end request
}

我不希望这个答案绝对解决你的问题,但它应该有所帮助。在应用上述更改后,请随时询问其他方向。

在对此答案的评论中回答OP的问题

您必须将getA的实施修改为以下效果:

function getA() {
    $(path).each(function(i,e){
        link = $(this).attr("href");
        getB(...).then(function(urls) {
            // NOTE: the `urls` parameter will have same value as the
            // `stuff` used in calling `fulfill(stuff)`
            console.log('type of urls: ' + typeof(urls) + urls);
            // getC();
            // you may also call getD() here
        }).then(function(urls) {
            // this additional `.then()` chain is not necessary as you could
            // have done what it is you wanted to do here inside the first `then(...)`
            // getD();
        });
    });
}

现在关于执行的顺序;将所有内容放在一起 - 您的原始代码段并在此答案中应用我对其所做的更改...

当您致电getA()时,会拨打getB()并在getB()成功执行之后 然后 {{1} }和getC()将分别执行 。总之,订单是getD() - > getA() - 如果getB()执行成功结果 - > getB() - > getC()

现在让我们定义另外两个函数getC()getWhatever

ohNo

我们稍后会修改function getWhatever(){ console.log("whateeveeer!"); } function ohNo(){ console.log("eeeeew!"); }

getA

function getA() { $(path).each(function(i,e){ link = $(this).attr("href"); getB(...).then(function(urls) { console.log('type of urls: ' + typeof(urls) + urls); getC(); }).then(function(urls) { getD(); }).catch(function(){ // you only reach this point if the outcome of getB was an error ohNo(); }); getWhatever(); }); } 进行了这一新的更改,以下是不同结果的执行顺序:

  • getA的结果成功时:

    getB - > getA() - > getB() - > getWhatever() - > getC()

  • getD()的结果成功时:

    getB - > getA() - > getB() - > getWhatever()

我希望你的所有问题现在得到充分解决。