如何修改bluebird promises中的express.res,并在另一个promise中使用res?

时间:2016-11-10 00:00:08

标签: javascript node.js express bluebird

我可能会过度思考这个,但请耐心等待......如果我有以下代码

app.get('/api/endpoint', function(req, res, next) {
    new Promise(function() {
        // doing something that takes lots of code
        return someJson
    })
    .then(function(someJson) {
        // analyze someJson with lots of code
    })
    .then(function() {
        // do more
    })
    // chain a bunch more promises here
    .then(function() {
        res.status(200).send(message)
    })
    .catch(function(err) {
        // error handling
    })
    .finally(function() {
        // clean up
    })
})

如果承诺链变得很长,导航端点可能会很痛苦。因此,我希望承诺的每一步都是它自己的功能(以简化上述代码)。所以我可以重写前2个承诺:

function findSomeJson() {
    return new Promise(function() {
        // doing something that takes lots of code
        return someJson
    })
}

function analyzeSomeJson(someJson) {
    return new Promise(function(someJson) {
        // analyze someJson with lots of code
    })
}

现在,这些函数中的每一个都可以在原始示例中使用,如下所示:

findSomeJson()
.then(function(someJson) {
    return analyzeSomeJson(someJson)
})
// etc...

但是,如果我需要在这些承诺中调整res,会发生什么?我是否每次都需要返回res并在res中存储someJson?而且,如果我必须使用next()会发生什么?如何确保在我的保证链末尾修改res?我不能在finally()中这样做,我是否必须在最后的承诺中这样做?

1 个答案:

答案 0 :(得分:1)

如果你真的希望能够在你的功能中改变res,你必须传递它。我认为传递它的最简单/最简洁的方法是使用bind,如下所示:

findSomeJson()
  .then(analyzeSomeJson.bind(this, res))
  .then(doMore.bind(this, res))
  .then(andEvenMore.bind(this, res))...

然后analyzeSomeJson定义如下所示:

// .bind makes it so that res is the first argument when it is called
function analyzeSomeJson(res, someJson) {
  return new Promise(function(someJson) {
    // analyze someJson with lots of code
  })
}

但我可能会尽量避免绕过res,以便只有您的控制器必须知道reqres。您可以将所有功能移动到一个或多个服务,并让控制器根据服务返回的内容确定res需要执行的操作。希望这将导致可维护/可测试的代码。

更新非常简单的服务示例

// endpoint.js
var jsonService = require('./jsonService.js');

app.get('/api/endpoint', function(req, res, next) {
  jsonService.getJson()
  // chain a bunch more promises here
  .then(function(json) {
    if(json === null) {
      return res.status(404).send('Not Found');
    }
    res.status(200).send(json);
  })
  .catch(function(err) {
      // error handling
  });
});

有许多方法可以实现您的服务,但实际上它只是您需要的“controller”或endpoint.js中的另一个.js文件。无论你出口什么,都将是你的“公共”方法。

// jsonService.js

// "public" methods
var service = {
  getJson: function() {
    return findSomeJson().then(analyzeSomeJson);
  }
};

module.exports = service;

// "private" methods
function findSomeJson() {
  return new Promise(function() {
      // doing something that takes lots of code
      return someJson
  });
}

function analyzeSomeJson(someJson) {
  return new Promise(function(someJson) {
      // analyze someJson with lots of code
  });
}