最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - Returning empty promise - Stack Overflow

programmeradmin3浏览0评论

I'm implementing this button in my app.

In my button component I have:

  @Input() callback: () => Promise<null>;
  onClick() {
    this.spinnerService.show();
    this.callback().then(() => {
      this.spinnerService.hide();
    }, () => {
      this.spinnerService.hide();
    });
  }

(I don't use async / await because the "tech lead" doesn't want me too)

The component template:

<my-button [callback]="doSomething">
</my-button>

Everything works fine when I pass this kind of code to the component's input:

doSomething = () => {
  return myService.doSomething()
    .toPromise()
    .then((response) => console.log('promise resolved'));
}

But I need to break from this function earlier:

doSomething() {
  if (condition) {
    return;
  }
  return myService.doSomething()
    .toPromise()
    .then((response) => console.log('promise resolved'));
}

I get

ERROR TypeError: Cannot read property 'then' of undefined

I've tried forcing a promise with the same result

  if (condition) {
    return Promise.resolve(null);
    // or
    return new Promise((resolve) => { resolve(null); });
  }

I'm implementing this button in my app.

In my button component I have:

  @Input() callback: () => Promise<null>;
  onClick() {
    this.spinnerService.show();
    this.callback().then(() => {
      this.spinnerService.hide();
    }, () => {
      this.spinnerService.hide();
    });
  }

(I don't use async / await because the "tech lead" doesn't want me too)

The component template:

<my-button [callback]="doSomething">
</my-button>

Everything works fine when I pass this kind of code to the component's input:

doSomething = () => {
  return myService.doSomething()
    .toPromise()
    .then((response) => console.log('promise resolved'));
}

But I need to break from this function earlier:

doSomething() {
  if (condition) {
    return;
  }
  return myService.doSomething()
    .toPromise()
    .then((response) => console.log('promise resolved'));
}

I get

ERROR TypeError: Cannot read property 'then' of undefined

I've tried forcing a promise with the same result

  if (condition) {
    return Promise.resolve(null);
    // or
    return new Promise((resolve) => { resolve(null); });
  }
Share Improve this question edited Mar 15, 2018 at 14:59 gyc asked Mar 15, 2018 at 14:34 gycgyc 4,3606 gold badges35 silver badges55 bronze badges 14
  • Which 'then' property is causing issue? – Sharcoux Commented Mar 15, 2018 at 14:38
  • @Sharcoux, the then from the button component. First code block – gyc Commented Mar 15, 2018 at 14:39
  • 2 (I don't use async / await because the "tech lead" doesn't want me too) StackOverflow can't help you with inter-company egos ;) – Pogrindis Commented Mar 15, 2018 at 14:40
  • Promise is not the issue here. You are focusing on the if(condition) located before the incriminated code. – Sharcoux Commented Mar 15, 2018 at 14:45
  • How strange. I tried something similar and it worked perfectly. Have you tried to check what that doSomething() method truly returns when the condition is met? I mean, you haven't got any library that breaks Promise.resolve, don't you? Can you do this and see what it returns? console.log(this.callback()) in your onClick() method – Oscar Paz Commented Mar 15, 2018 at 14:46
 |  Show 9 more comments

2 Answers 2

Reset to default 9

For this input

@Input() callback: () => Promise<null>;

there is no guarantee that it's assigned to proper value. Additional check if callback was specified should be added.

A safer way to manage this is to use async functions in these places because they consistently use promises:

  async onClick() {
    this.spinnerService.show();

    try {
      if (this.callback)
        await this.callback()
    } finally {
      this.spinnerService.hide();
    }
  }

doSomething is supposed to return a promise unconditionally, and this can also be addressed with async:

async doSomething() {
  if (!condition)
    return myService.doSomething().toPromise();
}

If async functions can't be used for some reason (although there are no good ones, because they are spec-compliant, first-class citizens in TypeScript), promises should be consistently processed in functions (also helpful for testing). doSomething isn't properly typed, and this allows improper function return. It should be:

  onClick(): Promise<void> {
    this.spinnerService.show();

    return Promise.resolve(this.callback ? this.callback() : undefined)
    .catch(() => {})
    .then(() => {
      this.spinnerService.hide();
    });
  }

and

doSomething(): Promise<void> {
  if (condition) {
    return Promise.resolve();
  }

  return myService.doSomething().toPromise();
}

And the type of callback will be Promise<void>, not Promise<null>.

Regular (non-arrow) doSomething method should be bound to this in constructor.

try this

doSomething() {
  if (condition) {
    return new Promise((resolve,reject)=> reject('Some Error Message'));
  }
  return myService.doSomething()
    .toPromise()
    .then((response) => console.log('promise resolved'));
}
发布评论

评论列表(0)

  1. 暂无评论