使用Angular 4如何在Observable中进行http promise调用?我正在使用AWS API Gateway和Cognito Federated帐户。我们必须使用apigClient.invokeApi来签署每个http调用。我想得到promise调用的结果,并将结果作为一个observable返回。下面的代码触发,但根本没有得到其余的可观察代码。当我订阅observable时,它永远不会访问subscribe中的代码。我也没有得到任何编译错误。任何帮助都会有所帮助。
public upload(image, fileType): Observable<FileReturnData> {
const apigClient = apigClientFactory.newClient({
accessKey: this.auth.cognitoAccessKey,
secretKey: this.auth.cognitoSecretKey,
sessionToken: this.auth.cognitoSessionToken,
invokeUrl: this.auth.URL
});
const data = new FileData()
data.image = image;
data.fileType = fileType;
const uploadPromise = apigClient.invokeApi({}, '/users/upload', 'POST', {}, {image: image, fileType: fileType});
const observable = new Observable<FileReturnData>(observer => {
uploadPromise.then(function (uploadResult) {
console.log(uploadResult); // I see this in the console
const fileReturnData = new FileReturnData();
const responseBody = JSON.parse(uploadResult.body);
fileReturnData.filename = responseBody.filename;
console.log('IN OBSERVABLE'); // I never get to this result
observer.next(fileReturnData);
observer.complete();
return () => console.log('upload image user observable disposed');
}).catch(function (uploadImageError) {
return () => console.error(uploadImageError);
});
});
return observable;
}
答案 0 :(得分:0)
我只对这样的Ajax调用使用嵌套的promises但我相信你的代码问题,使用observables和嵌套的promise是你过早地启动了invokeApi
http调用,调用/users/upload
当你期望它时没有完成,因此upload
等待观察者完成()返回的观察者的订阅者将会产生意想不到的后果,因为你在observer.complete()
中调用uploadPromise.then
可能有已经完成或我尚未完成。
看看这是否修复了您的代码:
public upload(image, fileType): Observable<FileReturnData> {
const apigClient = apigClientFactory.newClient({
accessKey: this.auth.cognitoAccessKey,
secretKey: this.auth.cognitoSecretKey,
sessionToken: this.auth.cognitoSessionToken,
invokeUrl: this.auth.URL
});
const observable = new Observable<FileReturnData>(observer => {
const data = new FileData()
data.image = image;
data.fileType = fileType;
apigClient.invokeApi({}, '/users/upload', 'POST', {}, {image: image, fileType: fileType})
.then(function (uploadResult) {
console.log(uploadResult); // I see this in the console
const fileReturnData = new FileReturnData();
const responseBody = JSON.parse(uploadResult.body);
fileReturnData.filename = responseBody.filename;
console.log('IN OBSERVABLE'); // I never get to this result
observer.next(fileReturnData);
observer.complete();
}).catch(function (uploadImageError) {
//handle error
});
});
return observable;
}
如果我完全理解你的场景,我个人觉得使用嵌套的http调用更容易管理。这是您可以使用的代码版本,仅使用promises,然后任何Observable都可以调用upload并等待其完成:
public upload(image, fileType): Promise<FileReturnData> {
const apigClient = apigClientFactory.newClient({
accessKey: this.auth.cognitoAccessKey,
secretKey: this.auth.cognitoSecretKey,
sessionToken: this.auth.cognitoSessionToken,
invokeUrl: this.auth.URL
});
const promise = new Promise<FileReturnData>((resolve, reject) => {
const data = new FileData()
data.image = image;
data.fileType = fileType;
//I moved this "invokeApi" call here because it does not seem like a factory method
//it seems like you start an ajax call when "invokeApi" is called
//so you must keep this all within the promise you are returning to callers
//of the upload function
apigClient.invokeApi({}, '/users/upload', 'POST', {}, {image: image, fileType: fileType})
.then(uploadResult => {
console.log(uploadResult); // I see this in the console
const fileReturnData = new FileReturnData();
const responseBody = JSON.parse(uploadResult.body);
fileReturnData.filename = responseBody.filename;
resolve(fileReturnData);
}, msg => {
reject(msg);
}).catch(ex => {
return () => console.error(ex);
});
});
return promise;
}