Javascript 如何正确地将同步代码执行的承诺串在一起
几天前我发布了一个类似的问题,但我做了一些修改,对这个问题的评论变得单调乏味,所以建议我问一个新问题。 我想同步执行四个方程。在这些等式中是HTTP请求。我有两个方程工作正常,但有一个方程涉及两个POST请求和一个GET请求。第二个请求依赖于第一个请求,第三个请求依赖于第二个请求 我尝试了几种不同的方法来实现这一点。我试着兑现我的承诺,回报我的承诺。各种各样的事情,没有运气。我不确定我会错在哪里 同步代码段:Javascript 如何正确地将同步代码执行的承诺串在一起,javascript,angular,promise,Javascript,Angular,Promise,几天前我发布了一个类似的问题,但我做了一些修改,对这个问题的评论变得单调乏味,所以建议我问一个新问题。 我想同步执行四个方程。在这些等式中是HTTP请求。我有两个方程工作正常,但有一个方程涉及两个POST请求和一个GET请求。第二个请求依赖于第一个请求,第三个请求依赖于第二个请求 我尝试了几种不同的方法来实现这一点。我试着兑现我的承诺,回报我的承诺。各种各样的事情,没有运气。我不确定我会错在哪里 同步代码段: this.getData1(user, userID).then(() => {
this.getData1(user, userID).then(() =>
{
this.getData2(user, userID)
.then(() =>
{
this.getData3(user, lan).then(() =>
{
this.userCheck(user);
})
});
});
我让getData2和getData3工作
getData1看起来像:
getData1(user: string, id: string){
console.log('grabbing CC information', id, user);
return new Promise((resolve, reject) =>
{
var status: string;
this._apiService.getAssertion(id).subscribe((data: any) =>
{
let assert = data.toString();
this._apiService.getToken(assert).subscribe((data: any) =>
{
let tkn = data.access_token.toString();
this._apiService.ccMeta(tkn, guid).subscribe((data: any) =>
{
parseString(data, (err, result) =>
{
if (err)
{
throw new Error(err);
}
else
{
status = result['entry']['content'][0]['m:properties'][0]['d:status'][0];
this.ccData.push(
{
key: 'userStatus',
value: status
})
}
});
});
});
});
resolve()
});
}
我以前也试过类似的方法。它也不起作用
apiService.getAssertion(id).then(assert =>
{
return apiService.getToken(assert.toString(), user);
}).then(data =>
{
return apiService.ccMeta(data.access_token.toString(), id);
}).then(parseStringPromise).then(information =>
{
this.ccData.push(
{
key: 'userStatus',
value: information.entry
});
});
在这个函数中,getAssertion函数是一个POST请求。getToken函数是另一个POST请求,它依赖于来自第一个POST请求的断言。最后,ccMeta是一个get请求,它依赖于来自第二个POST请求的令牌
我希望先执行getData1,然后执行getData2,然后执行getData3,最后执行userCheck。在getData1中,我需要断言,然后是令牌,然后是同步执行的get请求。上面的代码段未正确执行。在getToken公式中未正确使用该断言
我非常感谢您的帮助。因为这些HTTP调用实际上是可观察的,而不是承诺的,所以我认为您应该使用
管道和开关映射来研究可观察的组合。如果您仍然希望方法返回一个承诺,它可以如下所示:
getData1(user: string, id: string) {
console.log('grabbing CC information', id, user);
return new Promise((resolve, reject) => {
this._apiService.getAssertion(id)
.pipe(
switchMap((data: any) => {
let assert = data.toString();
return this._apiService.getToken(assert);
}),
switchMap((data: any) => {
let tkn = data.access_token.toString();
return this._apiService.ccMeta(tkn, guid);
}),
)
.subscribe(
data => {
parseString(data, (err, result) => {
if (err) {
reject(new Error(err));
return;
}
const status: string = result['entry']['content'][0]['m:properties'][0]['d:status'][0];
this.ccData.push({
key: 'userStatus',
value: status
});
resolve();
});
},
);
});
}
由于这些HTTP调用实际上是可观察的,而不是承诺的,因此我认为您应该使用pipe
和switchMap
等工具来研究可观察的组合。如果您仍然希望方法返回一个承诺,它可以如下所示:
getData1(user: string, id: string) {
console.log('grabbing CC information', id, user);
return new Promise((resolve, reject) => {
this._apiService.getAssertion(id)
.pipe(
switchMap((data: any) => {
let assert = data.toString();
return this._apiService.getToken(assert);
}),
switchMap((data: any) => {
let tkn = data.access_token.toString();
return this._apiService.ccMeta(tkn, guid);
}),
)
.subscribe(
data => {
parseString(data, (err, result) => {
if (err) {
reject(new Error(err));
return;
}
const status: string = result['entry']['content'][0]['m:properties'][0]['d:status'][0];
this.ccData.push({
key: 'userStatus',
value: status
});
resolve();
});
},
);
});
}
顺序地,而不是同步地。承诺总是异步的:-)您仍然在使用,并且在错误的位置调用resolve()
。我已经完成了您在上一篇文章中推荐的所有操作。我做了一个编辑,添加了我尝试过的一个东西@Bergi是第一行的新承诺吗?我想我必须这样设置,以便按顺序执行这四个功能。那是别人推荐给我的@BergiThat看起来像我在评论中发布的代码,而不是您应该在您的环境中尝试的代码。当然,您需要使用this.\u apiService
而不是apiService
,按顺序而不是同步地提供parseString
的预期版本。承诺总是异步的:-)您仍然在使用,并且在错误的位置调用resolve()
。我已经完成了您在上一篇文章中推荐的所有操作。我做了一个编辑,添加了我尝试过的一个东西@Bergi是第一行的新承诺吗?我想我必须这样设置,以便按顺序执行这四个功能。那是别人推荐给我的@BergiThat看起来像我在评论中发布的代码,而不是您应该在您的环境中尝试的代码。当然,您需要使用这一点。_apiService
而不是apiService
,提供parseString
等的预期版本。是否有一个简单的toPromise()
方法来处理可观察对象,这样您就可以避免使用新的Promise
构造函数?是的。有。我使用了.toPromise.then()。也没有运气@Bergi@Bergi这也是我的第一个想法,但由于我们需要首先将数据推送到this.ccData,我觉得在订阅中显式地这样做会更干净。但是,使用轻触
可以获得相同的结果,例如返回toPromise结果之前管道中的最后一个操作符。@ManuKpl我尝试了您的建议,但第三次调用api服务时出现错误。`类型“void”不可分配给类型“ObservableInput”。````。知道为什么吗?@newwebdev22我的错!实际上我忘了考虑parseString
方法。因为它返回void,所以从其回调返回值并不重要。我更新了我的答案,并将其包装在一个可观察的文件中。你可能想重构一下,但现在应该可以了。有没有一个简单的toPromise()
方法来处理可观察对象,这样你就可以避免新的Promise
构造函数?是的。有。我使用了.toPromise.then()。也没有运气@Bergi@Bergi这也是我的第一个想法,但由于我们需要首先将数据推送到this.ccData,我觉得在订阅中显式地这样做会更干净。但是,使用轻触
可以获得相同的结果,例如返回toPromise结果之前管道中的最后一个操作符。@ManuKpl我尝试了您的建议,但第三次调用api服务时出现错误。`类型“void”不可分配给类型“ObservableInput”。````。知道为什么吗?@newwebdev22我的错!实际上我忘了考虑parseString
方法。因为它返回void,所以从其回调返回值并不重要。我更新了我的答案,并将其包装在一个可观察的文件中。您可能想对其进行重构,但现在应该可以工作了。