How do I reference a promise returned from a chain

2019-07-16 18:58发布

问题:

This question already has an answer here:

  • How do I access previous promise results in a .then() chain? 15 answers

I'm new to promises, and I'm not sure if I'm using them correctly. I'm trying to make a calculation with some promises, so I chained a bunch of functions together. First I wrote it like the following, which worked, but doesn't seem like good code.

it('should verify CPC column', function() {
  ptor.findElements(protractor.By.className('aggRow')).then(function(promCells) {
    getAggCellColumn('CPC').then(function(promColCPC) {
      getAggCellColumn('Spend').then(function(promColSpend) {
        getAggCellColumn('Clicks').then(function(promColClicks) {
          promCells[promColCPC].getText().then(function(promStringCPC) {
            promCells[promColSpend].getText().then(function(promStringSpend) {
              promCells[promColClicks].getText().then(function(promStringClicks) {
                var floatCPC = parseFloat(promStringCPC);
                var floatSpend = parseFloat(promStringSpend);
                var floatClicks = parseFloat(promStringClicks);
                var result = Math.round((floatSpend / floatClicks) * 100) / 100;
                expect(floatCPC).toEqual(result);
              });
            });
          });
        });
      });
    });
  });
});

I researched promises some more and came up with the following:

it('should verify CPC column', function() {
  ptor.findElements(protractor.By.className('aggRow'))
    .then(getAggCellColumn('CPC')) 
    .then(getAggCellColumn('Spend')) 
    .then(getAggCellColumn('Clicks')) 
    .then(promCells[promColCPC + 2].getText()) 
    .then(promCells[promColSpend + 2].getText()) 
    .then(promCells[promColClicks + 2].getText()) 
    .then(function(promStringClicks) {
      var floatCPC = parseFloat(promStringCPC);
      var floatSpend = parseFloat(promStringSpend);
      var floatClicks = parseFloat(promStringClicks);
      var result = Math.round((floatSpend / floatClicks) * 100) / 100;
      expect(floatCPC).toEqual(result);
    });
});

This doesn't work, but I'm trying to get the result of findElements to be promCells. I also would like to reference the results from the getText() functions. Please let me know if I should be approaching this problem differently. Thanks!

I was also thinking about writing it like this...

it('should verify CPC column', function() {
  ptor.findElements(protractor.By.className('aggRow'))
    .then(function(promStringClicks) {
      var floatCPC = parseFloat(promCells[getAggCellColumn('CPC') + 2].getText());
      var floatSpend = parseFloat(promCells[getAggCellColumn('Spend') + 2].getText());
      var floatClicks = parseFloat(promCells[getAggCellColumn('Clicks') + 2].getText());
      var result = Math.round((floatSpend / floatClicks) * 100) / 100;
      expect(floatCPC).toEqual(result);
  });
});

回答1:

Promises concept in JS is function chaining, with error handling. In your case, you're okay with chaining only.

So in order to chain your calls, you must pass functions, that can return some value to be used by the next function of the chain.

Note that in unit testing, the its have to know when your chain ends, so you can expect the done function and call it when your chain has finished.

You finally would have something like:

it('should verify CPC column', function(done) {
    var promStringCPC, promStringSpend, promStringClicks;
    ptor.findElements(protractor.By.className('aggRow'))
        .then(function (promCells) {
            // Do something from async result like the following...
            promStringCPC = promCells.getAggCellColumn('CPC');
            promStringSpend = promCells.getAggCellColumn('Spend');
            promStringClicks = promCells.getAggCellColumn('Clicks');

            var floatCPC = parseFloat(promStringCPC);
            var floatSpend = parseFloat(promStringSpend);
            var floatClicks = parseFloat(promStringClicks);
            var result = Math.round((floatSpend / floatClicks) * 100) / 100;
            expect(floatCPC).toEqual(result);

            // You can do async additional stuff here...
            // return asyncResultOrNestedPromise
        }) 
        .then(function (result) {
            // ... and use the async's result here
        })
        .then(done);
});

Note that I didn't clearly get your specific case. Anyway I'm trying to make you understand the promises concept!