关于promise的反模式里面的几个典型案例我大致在这里总结一下:
1.嵌套承诺
使用场景:当我们需要多个参数去启动一个函数时,并且这几个参数需要分别请求多个接口时:
eg:
loadSomething().then(function(something) {
loadAnotherthing().then(function(another) {
DoSomethingOnThem(something, another);
});
});
在这里我们可以看到 有两个承诺,然后你需要对这两个承诺的结果进行一些处理,这样看起来很麻烦所以对应的解决方法是:
Promise.all([loadSomething(), loadAnotherThing()])
.then(function(res) {
DoSomethingOnThem(something, another);
});
你可以对比第一种写法就不难理解 第二种写法的优点了。
2.断链
使用场景:书写时的错误,不能收集错误
eg:
function anAsyncCall() {
var promise = doSomethingAsync();
promise.then(function() {
somethingComplicated();
});
return promise;
}
这样写的话 我们就不能捕获promise的错误了
所以需要改成:
function anAsyncCall() {
var promise = doSomethingAsync();
return promise.then(function() {
somethingComplicated()
});
}
这样写的话 不论是接收的结果 或者是出现的错误我们都可以捕获到
3.处理集合
使用场景:当我们需要对请求来的数据进行递归处理时:
function workMyCollection(arr) {
var resultArr = [];
function _recursive(idx) {
if (idx >= resultArr.length) return resultArr;
return doSomethingAsync(arr[idx]).then(function(res) {
resultArr.push(res);
return _recursive(idx + 1);
});
}
return _recursive(0);
}
首先这段代码看着就很烦人:作用就是对一个数字进行递归循环,知道这个数字达到某一个条件时 ,就返回之前递归时所请求的数据。这样不用仔细看就知道很麻烦。
所以:
function workMyCollection(arr) {
return Promise.all(arr.map(function(item) {
return doSomethingAsync(item);
}));
}
刚才说过 .all方法是 接收一组承诺并将其分解为结果数组,这样.all搭配map方法简单的多
4.判断承诺
使用场景:代码优化,整齐干净
eg:
var promise;
if (asyncCallNeeded)
promise = doSomethingAsync();
else
promise = Q.resolve(42);
promise.then(function() {
doSomethingCool();
});
这样的代码,明显是可以进行优化的,如下:
Promise(asyncCallNeeded ? doSomethingAsync() : 42)
.then(
function(value){
doSomethingGood();
})
.catch(
function(err) {
handleTheError();
});
这样显得代码就干净。
5.错误处理
使用场景:Promise的正统写法
somethingAsync
.then(function() {
return somethingElseAsync();
})
.catch(function(err) {
handleMyError(err);
});
这样的话我们就可以 清晰地对请求做出更明确的处理,使用.catch()捕获错误
6.遗忘的承诺
使用场景:有时多余的代码,会影响我们的执行。
doSomethingAsync().then(function(res) {
res = manipulateMeInSomeWay(res);
}, function(err) {
console.log(err);
});
return deferred.promise;
这样写会发现,我们把第一次的承诺忘记了,并且自己创造了一个承诺。并且我们发现这里有很多毫无意义的代码。所以我们只需要履行承诺就好:
return doSomethingAsync().then(function(res) {
return manipulateMeInSomeWay(res);
});