我正在尝试创建一个调用http请求的方法。如果请求返回401错误,我想重新登录并再次尝试请求。我的方法如下:
return this.http.post(url, this.cleanData(body), this.appendHttpHeaders(options))
.map(response => response)
.catch(error => {
if (error.status === 401) {
this.loginService.login(true).then(() => {
console.log("login should be finished: " + this.loginService.isLoggedIn());
return this.http.post(url, this.cleanData(body), this.appendHttpHeaders(options))
.map(response => response);
})
} else {
this.errorReportingService.reportHttpError(error);
return Observable.throw(error);
}
});
public login(forceLogin = false, loginCallback: () => any = null): Promise<String> {
...
console.log(1);
return new Promise((resolve, reject) => {
console.log(2);
this.popupLogin(loginCallback).then((result) => {
console.log(11);
resolve();
})
}).then(() => {
return new Promise((resolve, reject) => {
console.log(12);
resolve();
})
})
}
private popupLogin(loginCallback: () => any = null): Promise<String> {
...
console.log(3);
return new Promise((resolve, reject) => {
console.log(4);
this.handleLoginPopupFeedback(loginPopupHandle, loginCallback).then((result)=> {
console.log(9);
resolve();
})
}).then(() => {
return new Promise((resolve, reject) => {
console.log(10);
resolve("ok");
})
})
}
private handleLoginPopupFeedback(loginPopupHandle: Window, loginCallback: () => any = null): Promise<string> {
...
} else {
// ...popup is accessible, check values
let loginSuccessElement = loginPopupContent.getElementById('trucareOAuthLoginSuccess');
let loginFailureElement = loginPopupContent.getElementById('trucareOAuthLoginFailure');
if (!loginPopupHandle.closed &&
(loginSuccessElement === null || loginSuccessElement === undefined) &&
(loginFailureElement === null || loginFailureElement === undefined)
) {
console.log(5);
return new Promise((resolve, reject) => {
console.log(6);
setTimeout(() => {
console.log(7);
this.handleLoginPopupFeedback(loginPopupHandle, loginCallback).then((result) => {
console.log(8);
resolve();
}, 500)
})
});
}
...
}
return Promise.resolve("4");
}
问题是登录调用是异步的。有没有办法等待loginService.login()完成然后再次尝试请求?
编辑:根据评论修改了代码,但即使是console.log正在记录,调用仍然没有重复。但我甚至没有在浏览器的网络套接字中看到呼叫
答案 0 :(得分:0)
当我需要运行并重新运行一个promise,直到满足某个条件时,我使用这个我写的函数叫做ploop(promise loop):
// fn : function that should return a promise.
// args : the arguments that should be passed to fn.
// donefn : function that should check the result of the promise
// and return true to indicate whether ploop should stop or not.
// promise: A promise value that is used internally by ploop and should never
// be passed in by the caller of ploop.
var ploop = function(fn, args, donefn, promise) {
return (promise || Promise.resolve(true))
.then(function() {
return(fn.apply(null, args));
})
.then(function(result) {
var finished = donefn(result);
if(finished === true){
return result;
} else {
return ploop(fn, args, donefn, promise);
}
});
};
这是一个使用它的例子:
// Function that returns a promise
var searchForNumber = function(number) {
return new Promise(function(resolve, reject) {
setTimeout(function() {
var min = 1;
var max = 10;
var val = Math.floor(Math.random()*(max-min+1)+min);
console.log('Value is: ' + val.toString());
return resolve(val);
}, 1000);
});
};
var searchFor = 4;
var donefn = function(result) {
return result == searchFor;
};
console.log('Searching for: ' + searchFor);
ploop(searchForNumber, [searchFor], donefn)
.then(function(val) {
console.log('Finally found! ' + val.toString());
process.exit(0);
})
.catch(function(err) {
process.exit(1);
});
由于你的http.get返回一个promise,你应该能够将它与你的args一起传递给ploop。您的done函数可以检查结果中的迭代或其他条件,以确定是否继续运行promise。