angular - 在 Promise 链中使用 `.setTimeout()` 的正确方法是什么?

标签 angular typescript

在我正在构建的应用程序中,有一个用例需要引发第一个 API 调用,等待响应,然后使用响应中的信息引发第二个 API 调用。像这样:

firstAPI.call(some input)
            .then(firstResponse => {
                return secondAPI.call(firstResponse);
            })
            .then((secondResponse) => {
                //do something
            })
            .catch(error => {
                console.error(error);
            });

这些都很好。但是,目前由于某些原因,第二次API调用无法在第一次调用后立即引发,必须有一定的间隔才能起作用。然后我尝试像这样使用 .setTimeout():

firstAPI.call(some input)
            .then(firstResponse => {
                //save the response somewhere
            })
            .then(() => {
                // Wait 1.5s before calling the second API
                return this.sleep(1500);
            })
            .then(() => {
                return secondAPI.call(saved first response);
            })
            .then((secondResponse) => {
                //do something
            })
            .catch(error => {
                console.error(error);
            });

private sleep(milliseconds: number): Promise<Object> {
        return new Promise(resolve => {
            setTimeout(resolve, milliseconds)
        });
    }

我针对以下场景测试了这段代码:

1) 第一次和第二次调用都成功 - 工作正常并且休眠了 1.5 秒;

2) 第一次调用失败 - 工作正常,错误被捕获;

3) 第一次调用成功但第二次调用失败 - 没用;错误没有被捕获! 单元测试代码片段如下:

 describe('when first call succeeds but second call fails', () => {
        it('should log errorMsg', fakeAsync(() => {
            let mockFirstResponse: Promise<Object> = Promise.resolve(some mock response);            
            spyOn(firstAPI, 'call').and.returnValue(mockFirstResponse);
            spyOn(secondAPI, 'call').and.returnValue(Promise.reject(new Error('Oops!')));
            spyOn(console, 'error').and.callThrough();

            underTest.submit(); // Call my function
            tick(1500);

            expect(console.error).toHaveBeenCalled();
        }));
    });

单元测试失败,错误:

Error: Uncaught (in promise): Error: Oops! at resolvePromise (webpack:///~/zone.js/dist/zone.js:469:0 <- configuration/karma/karma-entry.js:128867) at webpack:///~/zone.js/dist/zone.js:528:0 <- configuration/karma/karma-entry.js:128926

.catch block 根本没有执行。

我的假设是 .setTimeout() 以某种方式打破了链条。执行此操作的首选方法是什么?

最佳答案

我很欣赏您的代码在做一些非常相似的事情,但试一试。

向链引入一个新的 promise ,它除了延迟链中下一个 block 的执行外什么都不做,如下所示:

firstAPI.call(someinput)
  .then(firstResponse => {
    return new Promise((resolve, reject) => {
      setTimeout(() => {
        resolve(firstResponse);
      }, 1500)
    })
  })
  .then(firstResponse => {
    return secondAPI.call(firstResponse);
  })
  .then((secondResponse) => {
    // do something
  })
  .catch(error => {
    console.error(error);
  });

总的猜测,需要延迟的原因可能是由于服务器在响应后执行了一些需要一两秒才能完成的处理,或者它可能重新索引或一些jiggery-pokery。

关于angular - 在 Promise 链中使用 `.setTimeout()` 的正确方法是什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52788412/

相关文章:

angular - 从表单控件 Angular 6 中删除验证器

angular - 在 Azure 的不同解决方案中部署 Angular 和 Web API?

typescript 错误 : Cannot write file 'index.d.ts' because it would overwrite input file

angularjs - Angular 2 - 组件如何识别 URL 更改?

android - tns 调试期间没有请求

javascript - Typescript:表达函数实例属性

angular - 路由守卫导致错误的路由导航行为

javascript - 了解 { [name : string]: } in Typescript 的用法

javascript - 如何在 react typescript 中获取输入字段类型作为 Prop

angular - 来自 Angular 输出的字符串连接发出,未按预期工作