尝试与JS API交互,但在Grunt任务运行时失败;我认为我的逻辑很困惑。我的步骤:
check_tokens
)refresh_tokens
)authorize_with_api
)< - 这是问题authorize_with_api
拒绝错误或使用令牌解决目前,Grunt任务报告UnhandledPromiseRejectionWarning
并且永远不会完成。如果我将对authorize_with_api
的通话注释掉,那么就会出错并正确退出,我会打印出最顶层的caught error!
消息。
为什么我不能从执行函数中返回一个承诺?我的逻辑出了什么问题?
/* global sdk, config, tokens */
return getTokens().then((p_tokens) => {
tokens = p_tokens;
return check_tokens(tokens);
}).then((tokens) => {
console.log('then() is called!');
}).catch((err) => {
console.error('caught error!', err);
});
function check_tokens(tokens) {
if(are_old(tokens)) { // returns true
return refresh_tokens(tokens);
}
return Promise.resolve(tokens);
}
function refresh_tokens(tokens) {
return new Promise(function(resolve, reject) {
sdk.refreshTokens(tokens.refresh_token, function(err, new_tokens) {
if(err) {
if(error.code === 'invalid_grant') {
return authorize_with_api();
}
reject('refreshTokens failed');
} else if(newTokens) {
resolve(new_tokens);
}
});
});
}
function authorize_with_api() {
return new Promise(function(resolve, reject) {
sdk.getTokens(config.auth_code, function(err, tokens) {
if(err) {
reject('getTokens failed');
} else if(tokens) {
resolve(tokens);
}
});
});
}
答案 0 :(得分:9)
从Promise构造函数(或其中的任何函数)返回不解析promise:
return new Promise(function(resolve, reject) {
sdk.refreshTokens(..., function(err, new_tokens) {
if(error.code === 'invalid_grant') {
return authorize_with_api();
} // ^--- this will not chain to the promise being created.
即使您没有从sdk.refreshTokens
回调中获得回报,而是在没有回调的情况下直接return authorize_with_api()
,结果仍然不会被链接。
要解决一个承诺,你不能从它的构造函数返回,但必须显式调用给定的一个回调(解析/拒绝):
return new Promise(function(resolve, reject) {
sdk.refreshTokens(..., function(err, new_tokens) {
if(error.code === 'invalid_grant') {
resolve(authorize_with_api());
} // ^--- must call resolve here
解决一个承诺实际上也会处理拒绝,所以无论authorize_with_api
解析还是拒绝,状态都会相应地向上传播。
我的建议是仍然保持return
语句以保持if
分支条件的预期视觉语义早期返回,但代码将在没有它的情况下工作,因为Promises can only be resolved once以及所有进一步的对reject
/ resolve
的来电被忽略。
return new Promise(function(resolve, reject) {
sdk.refreshTokens(..., function(err, new_tokens) {
if(error.code === 'invalid_grant') {
return resolve(authorize_with_api());
} // ^--- should still return here for readability - clean logic purposes
reject('refreshTokens failed'); // this will be ignored if the above `resolve` gets called first, no matter if you have the `return` statement
示例:
function success() {
return Promise.resolve('success');
}
function error() {
return Promise.reject('error');
}
function alwaysPending() {
return new Promise(() => {
return success();
});
}
function resolves() {
return new Promise((resolve) => {
resolve(success());
});
}
function rejects() {
return new Promise((resolve) => {
resolve(error());
});
}
alwaysPending().then(console.log); // doesn't log anything
resolves().then(console.log);
rejects().catch(console.log);

答案 1 :(得分:1)
如果满足以下条件,只需写last的else语句:
function authorize_with_api() {
return new Promise(function(resolve, reject) {
sdk.getTokens(config.auth_code, function(err, tokens) {
if(err) {
reject('getTokens failed');
} else if(tokens) {
resolve(tokens);
} else {
reject('tokens == undefined && err == undefined');
}
});
});
}