【问题标题】:Node.js Promises in nested callbacks in Promises in Promises not resolvingNode.js Promises in Promises in Promises 嵌套回调中的 Promise 未解决
【发布时间】:2019-01-14 12:22:59
【问题描述】:

我有以下无法解析的代码。 f2 解决了,所以我不会添加那个代码,我有问题是 f1。

我调用该函数并进入最里面,如果它调用函数“find”,该函数执行函数findId,它完美地返回Id,然后它执行editId,但它不解决document replaced + true 我知道它会在上下文日志出现时到达。

预期行为:

这应该解决回到最高承诺并到达context.done(),但它没有

这可能是一个简单的问题,就我在哪里放置新的承诺等而言,但我一直在努力解决这个问题的结构。

感谢您的任何见解。

module.exports = function (context, req) {
    var documentUrl = xyz;
    client.readDocument(documentUrl, (err, a) => {

        var f1 = fun1(a,b,c);
        var f2 = fun2(a,b,c);

        Promise.all([f1, f2]).then(function(results){ //parallel
            context.log(results[0], results[1]);
            context.done();
        });
    });
}

function fun1 (a,b,c){
if (a[0].stuff.length > 0) {
    var stuffArray = [];
    for (i = 0; i < a[0].stuff.length; i++) {
        if (a[0].stuff[i].morestuff !== null && a[0].stuff[i].otherstuff !== null) {
            if (a[0].stuff[i].Id== null) {
            var Id = a[0].id + '_' + i;
                var find = findId (a, Id, function(res){
                    context.log ("findFeedback: found");
                            context.log(res);                            
                            editId(context, res);
                });
                stuffArray.push(find);                
            }
        } else {
            stuffArray.push(i + " shouldn't have Id");
        }    
    }
    return Promise.all(stuffArray);
} else {
    return ('No stuff');
}
}
function findId(a, Id, callback) {    
    var documentUrl = myUrl/id;
        client.readDocument(documentUrl, (err, result) => {
            if (err) {
                if (err) {
                    return(err);
                }
            } else {
                callback(result);
             }
        });
}

function editId(context, res) {
    return new Promise((resolve, reject) => {
    var documentUrl = myUrl/res.otherId;
        client.readDocument(documentUrl, (err, result) => {
            if (err) {
                if (err.code == HttpStatusCodes.NOTFOUND) {
                    context.log('Post does not exist');
                    resolve('Post does not exist');
                } else {
                    context.log(err);
                    resolve(err);
                }
            } else {
                context.log('Post exists');
                // here i edit some stuff which works fine                            
                client.replaceDocument(documentUrl, result, (err, result) => {
                if(err) {
                    context.log(err);
                    resolve('Document replaced ' + false);
                } else {
                    context.log('replaced document ' + result);
                    resolve('Document replaced ' + true);
                    // This is where my context log ends it does not resolve back up 
                }
        });                

             }
        });
    });
};

【问题讨论】:

  • 字符串与布尔连接? fun1 在哪里?
  • 我不明白这意味着什么抱歉 - 我对此很陌生!
  • 你正在解析 'Document replaced ' + true 这是字符串和布尔似乎不正确
  • 嗯,这在其他地方对我有用,我很确定 - 我刚刚尝试将其全部设为字符串,但仍然存在同样的问题,我相信这与解决承诺有关。
  • 抱歉,我已将function f1 编辑为function fun1

标签: javascript node.js promise resolve


【解决方案1】:

这里的重点是让你的代码保持一致。

我认为您应该将所有回调函数包装到 Promise。这将使您的代码更清洁、更容易,而不是成为意大利面条。

我没有足够的上下文来测试。因此,我只是尝试稍微重构您的代码。希望它在某些方面对您有所帮助。

findId 函数应该返回一个 promise 而不是使用回调:

function findId(Id) {
  return new Promise((resolve, reject) => {
    var documentUrl = myUrl / id;
    client.readDocument(documentUrl, (err, result) => {
      if (err) {
        reject(err);
      } else {
        resolve(result);
      }
    });
  });
}

在 fun1 函数中,您在 for 循环中有异步代码。它不起作用,因为异步代码不会等到它为您提供结果。所以我通过将你需要调用findId 的id 推送到stuffArr 来重构。然后,我将这些 id 映射到 Promise 函数 findId 的列表中。通过这样做,我们可以使用 Promise.all 等待所有的 Promise 处理完毕。

function fun1(a, b, c) {
  if (a[0].stuff.length > 0) {
    var stuffArray = [];
    for (i = 0; i < a[0].stuff.length; i++) {
      if (
        a[0].stuff[i].morestuff !== null &&
        a[0].stuff[i].otherstuff !== null
      ) {
        if (a[0].stuff[i].Id == null) {
          var Id = a[0].id + "_" + i;
          var promise = findId(Id)
                .then(res => editId(context, res))
                .catch(err => i + " Some error");
          stuffArray.push(promise);
        } else {
          // don't know what you want to do here
        }
      } else {
        stuffArray.push(i + " shouldn't have Id");
      }
    }

    return Promise.all(stuffFindPromises);
  } else {
    return Promise.resolve("No stuff");
  }
}

希望这会有所帮助。

【讨论】:

  • 如果你不想要意大利面条,请使用 async 和 await。
  • 异步,等待或承诺都可以,我想。这里的重点是只坚持一件事。我上面已经解释过了。如果他有使用promise的想法,应该让一切都promise,这样他就可以轻松调试和阅读代码。
  • 我的观点是,使用 async 和 await 会消除嵌套,将代码大小减少 30%,并使代码更易于阅读。
  • @StevenSpungin 代码中有一个then 调用,您可以用await 替换它。几乎不占 30%。
  • @DatTran 感谢您的回复 - 我已经复制了这段代码,但它似乎产生了相同的结果(它以“替换文档”结束 - 问题是 1)我想推送 'i +“shouldnt让 Id" ' 进入 stuffArray 作为 results[0] 的一部分备​​份到第一个承诺,而不是将其推入 findId 2) 我确实想在完成 fun1 之前从 editId 解决
【解决方案2】:

findId 需要 return new Promise((resolve,reject) =&gt; { }); 包裹它。

然后您可以在findId 中调用editId 并将callback(result) 替换为resolve(editId(context, result));

之后将fun1 中的var find 替换为var find = findId (a, id) 并从findId 中删除回调要求

【讨论】:

    猜你喜欢
    • 2017-01-02
    • 2017-08-04
    • 2017-10-15
    • 2018-08-05
    • 1970-01-01
    • 2019-09-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多