承诺和周期

时间:2018-01-04 21:39:28

标签: javascript node.js promise async-await

有一系列的承诺,在我需要从数据库获取他的组和构造函数名称之后,第一个从数据库获取用户的id 这些可以是多份副本 结果循环进入循环。最终我只收到一个用户的对象

async(takeIds()
  .then(ids => {
    // console.log("ids", ids);
    for (var i = 0; i < ids.length; i++) {
      data.id = ids[i];
      await (takeIdvk(ids[i])
        .then(idm => {
          data.idvk = idm;
          takeIdg(data.id)
            .then(res => {
              takeNamesCycle(res, data)
                .then(data => {
                  console.log("data", data);
                })
                .catch(err => {
                  console.log(err);
                });
            })
            .catch(err => {
              console.log(err);
            });
        })
        .catch(err => {
          console.log(err);
        }));
    }
  })
  .catch(function(err) {
    console.log(err);
  }));

函数takeNamesCycle它与其他函数不同 (在其余的简单数据库请求中)

var takeNamesCycle = async(function(arr, obj) {
  return new Promise((resolve, reject) => {
    for (var i = 0; i < arr.length; i++) {
      var idg = arr[i];
      await (takeNames(arr[i])
        .then(names => {
          obj.idg[idg] = names;
        })
        .catch(err => {
          console.log(err);
        }));
    }
    resolve(obj);
  });
});

有可能简化这个吗? 我很感激

2 个答案:

答案 0 :(得分:1)

考虑使用真实async / await语法,而不是使用async()await()函数的库。

const ids = await takeIds();
// console.log("ids", ids);
try {
  for (var i = 0; i < ids.length; i++) {
    data.id = ids[i];
    const idem = await takeIdvk(ids[i]);
    data.idvk = idm;
    const res = await takeIdg(data.id);
    console.log("data", await takeNamesCycle(res, data));
  }
} catch(err) {
  console.log(err);
}

并确保avoid the Promise constructor antipattern

async function takeNamesCycle(arr, obj) {
  for (const idg of arr) {
    const names = await takeNames(idg);
    obj.idg[idg] = names;
  }
  return obj;
}

答案 1 :(得分:0)

发布的代码混合了代码中的awaitasync函数中的承诺链样式。

首先await不允许在它返回的值上调用.then.catch方法。原因是await返回的值从不承诺。 await仅在成功的promise操作后恢复执行并返回操作的结果。例如,

await (takeIdvk(ids[i])
.then(idm => {           // incorrect
     data.idvk = idm;
     // ... more code

变为

let idm = await takeIdvk(ids[i])   // await returns fulfilled value
data.idvk = idm;
// ... more code

换句话说,处理成功操作数据的代码是在await之后内联写入的,而不是作为参数传递给onfulfilled的单独.then处理程序。

承诺拒绝

如果等待的promise被拒绝,await运算符会抛出拒绝原因,而不会恢复函数执行。

可以在try / catch块中捕获拒绝,以便忽略错误,重复操作或将其替换为由应用程序要求确定的不同操作。 E.G。

let idm;
try {
    idm = await takeIdvk(ids[i])   // await returns fulfilled value
    data.idvk = idm;
    // ... more code
} catch( err) {
    console.log( "ignoring error + err);
    // the value of idm is undefined
}

另一方面,如果拒绝被视为致命,请不要将await放入try/catch块中 - 抛出的值将被捕获并用于拒绝由异步函数,就像在thencatch处理程序中抛出错误一样。

如果嵌套了对异步函数的调用,每个函数都使用await调用而没有任何try/catch块,则拒绝错误将从深层嵌套函数中冒出来并拒绝最外层异步函数调用返回的promise。最外层承诺上的单个.catch子句可用于防止未被捕获的承诺拒绝并通知发生故障。

<强>结论

如果您更熟悉该语法,请尝试使用普通的承诺链编写代码。一定要继续将其转换为async / await语法,但要注意async/await替代语法,并且它们不能在同一个函数中很好地混合。正如@Bergi已经说过的那样,从异步函数返回一个新的promise是一种反模式 - 异步函数已经返回一个承诺。