我正在尝试将承诺用于一个小项目。但是,我在理解如何通过功能更好地组织代码时遇到了一些问题。问题是,我希望我的功能能够处理问题,而我的主要代码来处理其他事情。因此,让我们看看此代码:
function doSomething (isGoingToResolve = true) {
return new Promise((resolve, reject) => {
if (isGoingToResolve) {
resolve("something")
} else {
reject("something else")
}
}).then(response => {
console.log("in my function",response)
}).catch(error => {
console.log("in my function",error)
})
}
doSomething().then(response => {
console.log("in my main call", response)
})
使用此代码,控制台将记录in my function something
和in my main call undefined
:https://jsfiddle.net/hkacvw2g/
所以我找到了解决问题的两种解决方案,但我只是不喜欢它们:
第一个是创建一个变量,在变量上使用.then()
,然后返回变量(https://jsfiddle.net/hkacvw2g/1/(:
function doSomething (isGoingToResolve = true) {
let promise = new Promise((resolve, reject) => {
if (isGoingToResolve) {
resolve("something")
} else {
reject("something else")
}
})
promise.then(response => {
console.log("in my function",response)
}).catch(error => {
console.log("in my function",error)
})
return promise
}
和第二个解决方案(https://jsfiddle.net/hkacvw2g/2/(:
function doSomething (isGoingToResolve = true) {
return new Promise((resolve, reject) => {
if (isGoingToResolve) {
resolve("something")
} else {
reject("something else")
}
}).then(response => {
console.log("in my function",response)
return new Promise(resolve => {
resolve(response)
})
}).catch(error => {
console.log("in my function",error)
return new Promise((resolve,reject) => {
reject(error)
})
})
}
我是否错过了解决问题的更好解决方案?
您可以简单地返回值(或重新输入错误(,然后将其在Promise链中解决:
:function doSomething (isGoingToResolve = true) {
return new Promise((resolve, reject) => {
if (isGoingToResolve) {
resolve("something")
} else {
reject("something else")
}
}).then(response => {
console.log("in my function",response)
return response;
}).catch(error => {
console.log("in my function",error)
throw error;
})
}
您可能不希望throw error
,这取决于您要如何处理拒绝。这样,当您重新输入错误时,请在调用doSomething()
方法时捕获它。
您可以编写一个tap
函数,点击前景链,并在传递结果时做某事,以及并行tapCatch
函数,以在重新磨损它们时插入错误:
const tap = fn => value => { fn(value); return value; };
const tapCatch = fn => reason => { fn(reason); throw reason; };
现在您可以将代码写为:
function doSomething(isGoingToResolve = true) {
(isGoingToResolve ?
Promise.resolve("something") :
Promise.reject("something else")
)
.then( tap (response => console.log("in my function", response)))
.catch(tapCatch(error => console.log("in my function", error)));
}
doSomething()
.then(response => console.log("in my main call", response));
但是,实际上您的第一个解决方案更好。它通过无意间忘记或不意识到您必须返回then
条款中的原始价值或在catch
条款中返回原始价值而降低了弄乱承诺链的风险。
您还可以用tap
之类的东西污染Promise
原型(我们将其称为thenDo
(,使其更容易使用:
Promise.prototype.thenDo = function(ifFulfilled, ifRejected) {
return this.then(
value => { ifFulfilled(value); return value; },
reason => { ifRejected(reason); throw reason; });
};
Promise.prototype.catchDo = function(ifRejected) {
return this.catch(reason => { ifRejected(reason); throw reason; });
};
现在您可以写
function doSomething(isGoingToResolve = true) {
(isGoingToResolve ?
Promise.resolve("something") :
Promise.reject("something else")
)
.thenDo (response => console.log("in my function", response))
.catchDo(error => console.log("in my function", error));
}