想象一下,我们处理数据的步骤很少。首先我们下载它,然后我们做很多次等等。 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');
});
});
});
});
});
}
是不是有更漂亮的图案?什么是反对意大利面的常见解决方案?
答案 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
})