处理数据的多个步骤,JS / Angular有什么好的模式?

时间:2016-09-22 11:49:39

标签: javascript angularjs angular-promise

想象一下,我们处理数据的步骤很少。首先我们下载它,然后我们做很多次等等。 C#中的代码看起来像几行 - 每一步一行。

据我所知,在JS / Angular中它看起来像这样:

function prepateAndGo() {

    loadData()
        .$promise.then((loadedData) => {

            prepareData(loadedData).$promise().then((preparedData) => {
           
                preprocessData(preparedData).$promise().then((preprocessedData) => {

                    andDoSmthElse(preprocessedData).$promise().then((andDoSmthElseData) => {

                        makeupData(andDoSmthElseData).$promise().then((makeupedData) => {

                            Console.log('finally, everything is loaded and processed, lets go');

                        });
                    });
                });
            });
        });
}

是不是有更漂亮的图案?什么是反对意大利面的常见解决方案?

4 个答案:

答案 0 :(得分:0)

由于您的每个回调本身都会返回承诺,因此您可以将.then()调用链接起来:

function prepateAndGo() {

    loadData().$promise()
        .then(loadedData => prepareData(loadedData).$promise())
        .then(preparedData => preprocessData(preparedData).$promise())
        .then(preprocessedData => andDoSmthElse(preprocessedData).$promise())
        .then(andDoSmthElseData => makeupData(andDoSmthElseData).$promise())
        .then(makeupedData => {
            Console.log('finally, everything is loaded and processed, lets go');
         });

}

此外,as Matt Way mentioned in his answer,如果您更改API以直接返回承诺,则可以完全摆脱箭头功能。

答案 1 :(得分:0)

您需要做的是创建返回承诺的实用程序函数。例如:

function prepareData(data){
    // do something with data and return a promise
    return $q.when(data);        
}

然后你可以很好地链接承诺。例如:

loadData()
    .then(prepareData)
    .then(preprocessData)
    .then(andDoSmthElse)
    .then(makeupData)
    .then(function(madeData){
        Console.log('finally, everything is loaded and processed, lets go');
    });

注意:代码不在我的掌控之中,但应该让你开始

答案 2 :(得分:0)

你听说过promise chaining吗?

action1()
    .$promise.then((result2) => action2(result2))
    .$promise.then((result3) => action3(result3))
    .$promise.then((result4) => action4(result4))
    .$promise.then((result5) => action5(result5))
    .$promise.then((finalResult) => console.log('Finally got it.'))

答案 3 :(得分:0)

使这些链更易读的简单方法就是将一些逻辑移到单独的函数中。所以:

function prepareAndGo() {
  loadData()
    .then(processData)
    .then(doSomethingElse)
    .then(whatever)
    .catch(err => console.log(err))
}

function processData(data) {
  ...
  return Promise.resolve(stuff)
}

function doSomethingElse(data) {
  ...
  return Promise.resolve(stuff)
}

function whatever(data) {
  ...
  return Promise.resolve(stuff)
}

稍微前瞻性的方法是使用async/await模式,您可以阅读更多here。目前还没有真正的可能在没有转换器的情况下使用async / await,因为缺乏支持(但这很快就会改变!)。

但是,您今天可以通过generators利用此模式,这是javascript ES2015规范中引入的新功能。 promise库Bluebird提供了一个名为coroutine的方法,它包装生成器函数并使它们像async函数一样运行。这是一个例子:

var Promise = require("bluebird")

let loadData = Promise.coroutine(function* (data) {

  let preparedData       = yield prepareData(data)
  let preprocessedData   = yield preprocessData(preparedData)
  let andDoSmthElseData  = yield andDoSmthElse(preprocessedData)
  let madeUpData         = yield makeupData(andDoSmthElseData)

  console.log('Everything is loaded and processed!')

  return madeUpData
})