承诺链与promise.all [英] promise chaining vs promise.all

查看:89
本文介绍了承诺链与promise.all的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个任务,使用量角器输入通知日期 在输入之前我需要清除内容的位置,所以我想出了这段代码

 this.Then(/^I should enter "Notification Date"$/, () => {
    const d = new Date();
    return orderCheckOutPage.pageElements.recipientNotificationDateMonth.clear().then(() => {
        return orderCheckOutPage.pageElements.recipientNotificationDateMonth.sendKeys(d.getMonth() + 1).then(() => {
            return orderCheckOutPage.pageElements.recipientNotificationDateDay.clear().then(() => {
                return orderCheckOutPage.pageElements.recipientNotificationDateDay.sendKeys(d.getDate()).then(() => {
                    return orderCheckOutPage.pageElements.recipientNotificationDateYear.clear().then(() => {
                        return orderCheckOutPage.pageElements.recipientNotificationDateYear.sendKeys(d.getFullYear())
                    })
                })
            })
        })
    })
});

我的朋友告诉我上述代码可以重构为

const promises = []; promises.push(orderCheckOutPage.pageElements.recipientNotificationDateMonth.clear()); promises.push(orderCheckOutPage.pageElements.recipientNotificationDateMonth.sendKeys(d.getMonth() + 1)); promises.push(orderCheckOutPage.pageElements.recipientNotificationDateDay.clear()); promises.push(orderCheckOutPage.pageElements.recipientNotificationDateDay.sendKeys(d.getDate())); promises.push(orderCheckOutPage.pageElements.recipientNotificationDateYear.clear()); promises.push(orderCheckOutPage.pageElements.recipientNotificationDateYear.sendKeys(d.getFullYear())); return promise.all(promises);

我听说了promise.all将会开始一个一个地解决

首先,它会转到第一个语句,并尝试解决它(在上述情况下是明确的月份)(如果是yashy),则跳至第二个语句,并尝试执行该语句[将密钥发送到月份]

这里清除和输入任务将并行进行

和任务根据承诺得到解决的时间执行

如果是这种情况,在清除之前将有执行sendkey的机会

如果我错了请纠正我... !!!!!

解决方案

量角器有其自己的承诺管理机制,称为控制流.要简单地理解控制流,您可以认为它是一个队列.

当nodejs逐行执行您的Protractor脚本时,如果该行中的表达式返回一个promise,则控制流将把promise添加到队列中.

所有行执行完毕后,您将获得一个Promise队列,此时您的测试尚未完成,因为控制流将使您的测试等待队列中的所有Promise都被执行.现在,控制流将从队列中弹出一个Promise,然后执行并等待其完成,然后是下一个Promise.

因此,通过这种机制,您的脚本可以按照您编写时的顺序执行 记录下来.实际上,控制流所执行的操作比我在这里所说的要复杂.

在您的情况下,您无需使用嵌套然后链接的代码,您的代码就像回调金字塔一样,并不代表promise的优势(承诺是解决回调金字塔).您的代码可以很简单,如下所示:

const d = new Date();
//input month
orderCheckOutPage.pageElements.recipientNotificationDateMonth.clear();
orderCheckOutPage.pageElements.recipientNotificationDateMonth.sendKeys(d.getMonth() + 1);
//input day
orderCheckOutPage.pageElements.recipientNotificationDateDay.clear();
orderCheckOutPage.pageElements.recipientNotificationDateDay.sendKeys(d.getDate());
//input year
orderCheckOutPage.pageElements.recipientNotificationDateYear.clear();
orderCheckOutPage.pageElements.recipientNotificationDateYear.sendKeys(d.getFullYear());

对于您的情况,无需使用promise.all(),因为代码的所有交互都不会从页面中获得某些价值.我将举一个例子来帮助您学习,在这种情况下最好使用promise.all():

假设我有一个页面,它显示了价格和金额.我需要按价格*金额计算费用.

使用嵌套然后链接:

var fee = ele_price.getText().then(function(price){

    return ele_amount.getText().then(function(amount){
        return price * amount;
    });
});

fee.then(function(fee){
    console.log(fee);
});

使用promise.all():

var fee = promise.all([
  ele_price.getText(),
  ele_amount.getText()
])
.then(function(datas){
    var price = datas[0];
    var amount = datas[1];
    return price * amount;
});

fee.then(function(fee){
    console.log(fee);
});

因此请使用promise.all(),那么一个then()就足够了.这使您的代码比嵌套然后链接的代码更具可读性.

希望您现在了解为什么在您的情况下无需使用promise.all().

i have a task to enter the notification date using protractor where i need to clear contents before entering so i have came up with this code

 this.Then(/^I should enter "Notification Date"$/, () => {
    const d = new Date();
    return orderCheckOutPage.pageElements.recipientNotificationDateMonth.clear().then(() => {
        return orderCheckOutPage.pageElements.recipientNotificationDateMonth.sendKeys(d.getMonth() + 1).then(() => {
            return orderCheckOutPage.pageElements.recipientNotificationDateDay.clear().then(() => {
                return orderCheckOutPage.pageElements.recipientNotificationDateDay.sendKeys(d.getDate()).then(() => {
                    return orderCheckOutPage.pageElements.recipientNotificationDateYear.clear().then(() => {
                        return orderCheckOutPage.pageElements.recipientNotificationDateYear.sendKeys(d.getFullYear())
                    })
                })
            })
        })
    })
});

my friend told me the above code be can refactored as

const promises = []; promises.push(orderCheckOutPage.pageElements.recipientNotificationDateMonth.clear()); promises.push(orderCheckOutPage.pageElements.recipientNotificationDateMonth.sendKeys(d.getMonth() + 1)); promises.push(orderCheckOutPage.pageElements.recipientNotificationDateDay.clear()); promises.push(orderCheckOutPage.pageElements.recipientNotificationDateDay.sendKeys(d.getDate())); promises.push(orderCheckOutPage.pageElements.recipientNotificationDateYear.clear()); promises.push(orderCheckOutPage.pageElements.recipientNotificationDateYear.sendKeys(d.getFullYear())); return promise.all(promises);

I heard promise.all will start resolving promises one by one

first it would go to first statement and try to resolve if it [here in the above case is clear month] if is asynch the it would jump to second one and try to execute the statement [sending keys to month]

here both the tasks of clearing and entering will be run parallely

and tasks are executed based on the time promises get resolved

if it is that case will there be chances of sendkeys being exeuted before clearing

correct me if i am wrong...!!!!!

解决方案

Protractor has its own promise manage mechanism called control flow, To understand control flow simply, you can think it is a queue.

When nodejs execute your Protractor script line by line, if the expression in the line return a promise, control flow will add the promise into the queue.

After all lines execute done, you will get a promise queue, at this time point your testing had not finish yet, because control flow will make your testing to wait all promise in the queue be executed. Now control flow will pop a promise from the queue and execute and wait it complete, then next promise.

So with such mechanism, your script can be executed as the order as you write down in file. Actually what control flow did is more complex than I said here.

You no need to use nested then chain in your case, your code like the callback pyramid, not represent the advantage of promise (promise is to resolve callback pyramid). Your code can be simple as below:

const d = new Date();
//input month
orderCheckOutPage.pageElements.recipientNotificationDateMonth.clear();
orderCheckOutPage.pageElements.recipientNotificationDateMonth.sendKeys(d.getMonth() + 1);
//input day
orderCheckOutPage.pageElements.recipientNotificationDateDay.clear();
orderCheckOutPage.pageElements.recipientNotificationDateDay.sendKeys(d.getDate());
//input year
orderCheckOutPage.pageElements.recipientNotificationDateYear.clear();
orderCheckOutPage.pageElements.recipientNotificationDateYear.sendKeys(d.getFullYear());

For your case, no need to use promise.all(), because all interaction of your code not to get some value from page. I will give an example to help you learn in which case it's better to use promise.all():

Assume i have a page and it display a price and a amount. I need to calculate the fee by price * amount.

Use nested then chain:

var fee = ele_price.getText().then(function(price){

    return ele_amount.getText().then(function(amount){
        return price * amount;
    });
});

fee.then(function(fee){
    console.log(fee);
});

Use promise.all():

var fee = promise.all([
  ele_price.getText(),
  ele_amount.getText()
])
.then(function(datas){
    var price = datas[0];
    var amount = datas[1];
    return price * amount;
});

fee.then(function(fee){
    console.log(fee);
});

So use promise.all(), one then() is enough. This makes your code more readable than nested then chain.

Hope you now understand why no need to use promise.all() in your case.

这篇关于承诺链与promise.all的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆