简体   繁体   中英

Should I create a new Promise in each class method?

I would like to utilize the Promises in my class methods. In Promise antipatterns I read that creating a new promise for each new function is considered to be bad.

However, I don't want to return un-related promises in my project, so I thought of doing something like this:

class MyClass {

  async getToken() {
    return new Promise(
      (resolve, reject) => {
        // . . .
        const token_str = '<response_from_http_request>';
        resolve(token_str);
      }
    )
  }

  async doSomething(token) {
    return new Promise(
      (resolve, reject) => {
        const result = // . . .
        resolve(result);
      }
    )
  }

  async doAnotherSomething(token) {
    return new Promise(
      (resolve, reject) => {
        const result = // . . .
        resolve(result);
      }
    )
  }

}

Then I would use it like this:

let instance = new MyClass();

(async () => {
    const token = await instance.getToken();

    const result1 = await instance.doSomething(token);
    console.log(result1);

    const result2 = await instance.doAnotherSomething(token);
    console.log(result2);

})();

Does this seem like a valid way to do this, or is this an antipattern too? And if so, how can I avoid writing code like this?


EDIT: What if I need to make several sequential http calls, perform some actions on the results and then return a Promise based on it?

The way I understand, if I don't make a new Promise, I have to return the one made by the got.js library, which includes the http response data.

Instead, I want to return a Promise which contains the result of my class method.

Example:
  async getCityWeather( city_name ) { return new Promise( (resolve, reject) => { // get the city id based on its name const city_id = await got(`https://my-api/getCityIdByName/${city_name}`); // now get the weather info for the city with id `cityid` const weather_info = await got(`https://my-api/weatherById/${city_id}`); // make an object to return const temperature = { weather_info.temp_min, weather_info.temp_max, } resolve(temperature); // ... all error handling are omitted } ) } 

I don't want to return a Promise that contains got.js return values, I want to return my values based on the http request calls.

async functions always return a Promise .

A function/method will return a Promise under the following circumstances:

  • You explicitly created and returned a Promise from it's body.
  • You returned a Promise that exists outside the method.
  • You marked it as async .

Since you can await a Promise and instance.doSomething is already an async-marked method, you can await it without needing to explicitly return a Promise.

Simply return it's result like you would in a regular synchronous method.

I don't want to return un-related promises in my project...

Unless you're actually doing something asynchronous in your method (accessing the file system, database calls, timers etc...), you don't need to wrap it in a Promise , nor await it when you need a result.

The most usual case where you actually need to wrap something in a Promise is if you have an asynchronous function that works using callbacks but you want to use it as a Promise .

 // plain old callback-style asynchronous functions: const getFooViaCallback = callback => { setTimeout(() => { callback('foo') }, 150) } const getBarViaCallback = callback => { setTimeout(() => { callback('bar') }, 150) } class Foo { constructor() {} getFooViaPromise() { // wrap callback-style code in a Promise // so we can await it. return new Promise(resolve => { getFooViaCallback(result => { resolve(result) }) }) } getBarViaPromise() { // wrap callback-style code in a Promise // so we can await it. return new Promise(resolve => { getBarViaCallback(result => { resolve(result) }) }) } getBaz() { // no reason to wrap this in a Promise, // since it's a synchronous method. return 'baz' } async getFooBarBaz() { const foo = await this.getFooViaPromise() const bar = await this.getBarViaPromise() const baz = this.getBaz() return foo + ',' + bar + ',' + baz } } ;(async() => { const foo = new Foo() const result = await foo.getFooBarBaz() console.log('foo.getFooBarBaz() result: ', result) })() 

I've ommited error handling in the above snippet for brevity but you should use throw in async -marked methods to raise errors. It's the equivalent of calling .reject() within a Promise.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM