【问题标题】:Should promises be avoided in synchronous functions? [duplicate]应该在同步函数中避免 promise 吗? [复制]
【发布时间】:2018-06-18 08:03:59
【问题描述】:

我目前正在尝试美化一些 NodeJS 遗留代码,并且在这样做时提出了我找不到任何最佳实践或入门指南的问题(如果您知道,请与我分享)。

我们的目的不是简单地看到可以通过 Promises 组合同步和异步代码(这很清楚),而是为什么应该例如如果函数的同步处理是明确的,那就去同步代码。这意味着在同步代码中简单地添加一个 Promise 会有什么缺点?有吗?例如。在运行时,或者更重要的是,在异步流程中?

例如以下面的异步函数为例:

Foo.prototype.addNode = function addNode() {
  var self = this;
  return new Promise(function (resolve, reject) {
    var node = new Node(self.getNodes().getLastId() + 1);
    resolve (self.getNodes().add(node));
  });
}

在我们的业务逻辑中,这个函数确实应该是异步的,因为这是在承诺链中递归调用的。

但是,add 函数是同步处理的,因为这是一个简单的 Array.push() 通用元素,并经过了一些验证。

GenericElementList.prototype.add = function add(T) {
  if (this.T.length === 0) {
    this.T.push(T);
    this.typeOfT = T.constructor;
    return this;
  }
  else {
    if (!(T.constructor === this.typeOfT)){
      this.T.push(T);
      return this;
    }
    else {
      throw new IllegalArgumentError('Invalid type of element to push into array! Was: ' + T.constructor.name + ' but should be: ' + this.typeOfT.name + '!');
    }
  }
};

(为了避免混淆:self.getNodes() 返回一个元素 Node,它是一个 GenericElementGenericElementListGenericElements 的列表数据结构。)

现在我的问题是:如果我们将 Promise 添加到 add-function 中,在这些方法的异步处理中是否存在运行时或流程方面的缺点?有什么理由避免这种情况吗?或者唯一的缺点是一些样板代码?

【问题讨论】:

  • 在同步函数中是否应该避免使用promise?,如果你有同步函数,使用promise是在浪费资源。 Promise 的作用是,当其他一些代码处理并且你不想等待它时,它会执行一些代码。
  • 我不明白。在您的示例中,add 同步的,它只是粗暴操作。你为什么说它可以被同步处理?是的。
  • 我认为没有充分的理由来处理 Array.push 异步。
  • 我想你的问题在这里解决了:stackoverflow.com/questions/27715275/…
  • @ThomasKleßen 我以前看过这篇文章,它回答了存在差异的问题,但恕我直言并没有说在同步调用中避免承诺(或者我可能忽略了这一点)。但我目前正在重构 NodeJS 中的一些“遗留”组件,它们被递归调用并异步处理,目前害怕通过将它们更改为同步处理来破坏某些流程。流程中的递归使这变得更加复杂。

标签: javascript node.js asynchronous promise


【解决方案1】:

在 javascript/node 同步执行中,无论你如何表达它都保持同步。举个例子

console.log("stage 1")
findIndex(data, 2, (err, index)=>{
    console.log(err, index)
})
console.log("stage 3")

function findIndex (arr, val, callback){
    console.log("stage 2")
    var idx =arr.indexOf(val)
    if(idx==-1) return callback(new Error("value not found"))
    return callback(null, idx)
}

虽然异步或可以说 I/O 绑定执行始终是异步的。不管怎么表达(有人认为 es6 async/await 让异步执行同步)

console.log("stage 1")
setTimeout(()=>{
    console.log("stage 2")
}, 0)
console.log("stage 3")

打开你的 js 控制台,找出不同之处和执行流程

Promise 也一样

现在循环内的异步函数

  1. 当异步任务依赖时,顺序迭代很有用。 (一个操作的结果需要反馈另一个(/s))
(function loop(i) {
if(i==4) return
setTimeout(function() {
  console.log('Working on index', i);
  loop(++i)
 }, 1000);
})(0);
  1. 当异步任务相互独立时,并行执行很有用。
var data = [1,2,3,4]
data.map(val=>{
    return new Promise((resolve, reject) => {
        setTimeout(function() {
         console.log('Working on index', val);
         // pass data in reslove() and get when promise resloved
        })
    });
})
Promise.all(data)
.then(done=>{
    // get passed data
    console.log(done);
})
.catch(err=>{
    console.log(err);
})

从中获得更多 https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise

【讨论】:

  • 因此可以得出结论,如果我们将一些异步样板代码添加到同步函数中,我们只是改变了如何处理返回值的方式?所以结果保持不变我们只是以不同的方式接收它?在向同步函数添加承诺的情况下,这将导致不必要地使用资源。
  • @Vegaaaa 检查更新
猜你喜欢
  • 2017-04-16
  • 2017-12-14
  • 1970-01-01
  • 2018-07-29
  • 2014-10-24
  • 2018-06-04
  • 1970-01-01
  • 2014-10-05
  • 2012-10-14
相关资源
最近更新 更多