简体   繁体   中英

How do I prevent promises from losing context without arrow function

I have the following code...

page.goToPage().then(() => page.isLoaded()).then(() => driver.quit());

This seems to be too verbose but when I try...

page.goToPage().then(page.isLoaded).then(driver.quit);

I get errors because in page.isLoaded the context of this changes to the promise.

Is there a way I can do the later without an arrow function?

Use promises properly. There is nothing too verbose about arrow notation, but a good practice is to make sure that any then handler is provided with the information it needs to do the job you need it to do.

class Driver {
  quit() {
    console.log("quit");
  }
}

class Page {
  constructor() {
    this.driver = new Driver();
  }

  goToPage() {
    console.log("gotopage");
    return new Promise((resolve, reject) => {
      // Things happen here. If they go wrong, you call reject() with an argument that
      // is a useful error object. If they succeed, you call resolve() with data that the
      // next handler should be working with. In this case I'm passing "this" so that the
      // page is available to the next link in the chain.
      resolve(this);
    });
  }

  waitForLoad() {
    console.log("waitforload");
    return new Promise((resolve, reject) => {
      // let's have this fail half the time, for demonstration purposes.
      var l = Math.random();
      if (l < 0.5) {
        resolve(this.driver);
      } else {
        reject(new Error("error"));
      }
    });
  }
}

Now, you have proper promise-using code:

var p = new Page();

p.goToPage()
 .then( page => page.waitForLoad())
 .then( driver => driver.quit())
 .catch( e => console.error(e));

Each then handler now gets exactly the input it needs to call the functions it needs to call, without trying to bust through their own scope, and without having to .bind() anything.

(If you need .bind() in normal code, that's usually the sign you are fighting against JavaScript in terms of ensuring sope, rather than making use of the various ways JavaScript lets you ensure correct scope)

Like Mike suggested after finding the answer it doesn't seem any less verbose...

page.goToPage()
    .then(page.isLoaded.bind(page))
    .then(driver.quit.bind(driver));

(Thanks @GetOffMyLawn)

I will leave the question unanswered in case someone has a creative solution.

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