Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/angular/32.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 如何正确地将同步代码执行的承诺串在一起_Javascript_Angular_Promise - Fatal编程技术网

Javascript 如何正确地将同步代码执行的承诺串在一起

Javascript 如何正确地将同步代码执行的承诺串在一起,javascript,angular,promise,Javascript,Angular,Promise,几天前我发布了一个类似的问题,但我做了一些修改,对这个问题的评论变得单调乏味,所以建议我问一个新问题。 我想同步执行四个方程。在这些等式中是HTTP请求。我有两个方程工作正常,但有一个方程涉及两个POST请求和一个GET请求。第二个请求依赖于第一个请求,第三个请求依赖于第二个请求 我尝试了几种不同的方法来实现这一点。我试着兑现我的承诺,回报我的承诺。各种各样的事情,没有运气。我不确定我会错在哪里 同步代码段: this.getData1(user, userID).then(() => {

几天前我发布了一个类似的问题,但我做了一些修改,对这个问题的评论变得单调乏味,所以建议我问一个新问题。 我想同步执行四个方程。在这些等式中是HTTP请求。我有两个方程工作正常,但有一个方程涉及两个POST请求和一个GET请求。第二个请求依赖于第一个请求,第三个请求依赖于第二个请求

我尝试了几种不同的方法来实现这一点。我试着兑现我的承诺,回报我的承诺。各种各样的事情,没有运气。我不确定我会错在哪里

同步代码段:

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,所以从其回调返回值并不重要。我更新了我的答案,并将其包装在一个可观察的文件中。您可能想对其进行重构,但现在应该可以工作了。