【问题标题】:Nested Promises Stuck嵌套的 Promise 卡住了
【发布时间】:2014-10-13 17:38:58
【问题描述】:

下面的代码卡住了:

var Promise = require('promise');
var testPromise = function(){
  return new Promise(function(fulfill, reject){

    element.all(by.repeater('item in menu.items')).first().then(function(el){
        console.log('test f');
        fulfill(el);
        console.log('test fe');
    });

  });
};

...由以下调用:

testPromise().then(function(el){
    console.log('test successful '+el);
});

控制台打印

test f
test fe

然后卡住,不再执行代码。尽管已经调用了完成,但它永远不会到达 then。

如果使用嵌套承诺是一种反模式,那么我如何在没有嵌套承诺的情况下执行以下操作:

var getMenuItemEl = function(itemName){
  return new Promise(function(fulfill, reject){

    var elFound;
    element.all(by.repeater('item in menu.items')).then(function(els){
        async.each(els, function(el, callback){
            el.getText().then(function(text){
                console.log('getMenuItemEl:'+text);
                if(text === itemName){
                    elFound = el;
                }
                callback(); 
            });
        }, function(err){
            console.log('complete '+elFound);
            if(elFound){
                console.log('fulfill');
                fulfill(elFound);
                console.log('after fulfill');
            }else{
                reject('no item found');
            }
        });

    });

  });
};

在调用完成后这也会卡住

【问题讨论】:

  • 您使用的是哪个promise 库?
  • 请注意,您将 an antipatternnew Promise 一起使用。避免它可能会解决问题,尽管您的代码确实应该按原样工作。
  • 我把它读作“嵌套的 promises 很烂”
  • promise 库是 then/promise
  • 我也被量角器api弄糊涂了

标签: javascript node.js asynchronous promise protractor


【解决方案1】:

如果使用嵌套承诺是一种反模式,那么我如何在没有嵌套承诺的情况下执行以下操作

您不会使用async 库。由于您的所有方法(element.all()el.getText() 等)都已经返回了 Promise,因此您无需返回节点样式的错误回调。来自my "rules for promises"每个异步函数(即使是回调)都应该返回一个承诺,并使用你的库的方法来组合它们。你真的不需要自己调用Promise 构造函数。您在那里进行的迭代可以通过map 而不是els 轻松完成,然后将所有单个promise 与Promise.all 一起收集。

function getMenuItemEl(itemName) {
    return element.all(by.repeater('item in menu.items'))
    .then(function(els){
        return Promise.all(els.map(function(el) {
            return el.getText()
            .then(function(text){
                console.log('getMenuItemEl:'+text);
                return (text === itemName) ? el : null;
            });
        }));
    })
    .then(function(foundEls) {
        for (var i=0; i<foundEls.length; i++)
            if (foundEls[i] != null) {
                console.log('fulfill');
                return foundEls[i];
            }
        throw new Error('no item found');
    });
}

【讨论】:

  • 感谢您的帮助。同步执行此操作非常简单。
  • 当我运行这个新代码时错误仍然存​​在。在最后一个getMenuItemEl之后就卡住了,它永远不会达到并且没有抛出错误
  • 我不知道。也许您使用的 API 中存在错误,并且它返回了未决的承诺?尽管在您的原始脚本中,您调用 fulfill 然后什么都没有发生,但在执行最后一个回调之后,它看起来似乎存在无限循环左右。您能否设置一个重现问题的最小演示,以便我们进行调查?
  • 我也不明白这是如何工作的。当你返回 foundEl[i] 时会发生什么,这个函数是返回一个 Promise 还是一个元素?
  • return foundEl[i] 的回调函数确实返回了一个元素。此回调传递到的 .then(…) 返回此元素的承诺,因为它在执行回调之前等待 foundEls
【解决方案2】:

以下代码解决了我的问题,主要是我对量角器api的了解不够

var doClickMenuItemEl = function(itemName){
  return element.all(by.repeater('item in menu.items')).filter(function(elem, index) {
    return elem.getText().then(function(text) {
        return text === itemName;
    });
  }).then(function(els){
    els[0].click();
  });   
};

它还在https://github.com/angular/protractor/issues/379 上说

是的,这是从 webdriver promises 继承的,不幸的是,它们并不完全符合 promise A+。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-06-23
    • 2021-10-08
    • 2016-11-24
    • 1970-01-01
    相关资源
    最近更新 更多