【问题标题】:Use Promises Correctly in Synchronous Project在同步项目中正确使用 Promise
【发布时间】:2017-11-28 08:07:47
【问题描述】:

我有一个标准的 JavaScript 项目。它主要与一些回调同步。我需要使用 3rd 方库来简化事情。问题是这个库是基于异步方法和 Promises 的。我以前从未真正使用过这种方法。

我有一种情况,我只需要something = get_info(); 代码都是非常模块化的,所以有多个函数调用堆叠起来。问题是这个get_info 是异步的。我只是不知道如何在我的项目中使用这个异步函数,而不必重写整个东西。

编辑:以下是类似代码的示例

function my_class() {
    this.do_something( data ) {
        if ( this.get_data() == data ) {
            do_the_thing();
        }
    }

    this.get_data = function() {
        return library.get_info( arguments ); //can't do this, returns a promise
    }
}

var stuff = new my_class();

for ( var i = 0; i < len; i++ ) {
    stuff.do_something( i )
}

同样,我们的目标是不重写应用程序的整个部分。想法?

【问题讨论】:

  • 没有实际代码,除了“学习如何使用异步代码”无话可说
  • 是的,我就是这么想的。这是一个非常深入的项目。我将尝试简化一些代码,以举例说明我在说什么。
  • 我添加了一些与情况类似的内容,但要简化得多。
  • 您发布的代码中没有(明显的)promise,那么您怎么能期望得到关于如何在您的代码中正确使用promise 的答案呢?
  • @JaromandaX,如果我知道该怎么做,我就不会问了。感谢您对我的耐心。问题是 third_party_library.get_info( arguments ) 是返回承诺的内容。我真的需要让函数返回值,但这似乎是不可能的。

标签: javascript asynchronous promise


【解决方案1】:

没有需要承诺链中调用的每个函数。您可以在 Promise 链中任意调用同步或异步函数。您只需要考虑在哪里等待解析的值。

您的代码离工作不远了,只需添加一个.then() 块即可使其工作。

下面的工作示例:

function my_class() {
  this.do_something(data) {
    //Call the promise-returning function
    this.get_data()
      .then((resolvedData) => {
        //Wait for promise resolution
        //and compare the resolved value to 'data'
        if (resolvedData === data) {
          do_the_thing();
        }
      })
      .catch();
  }

  this.get_data = () => {
    return library.get_info(arguments);
  }
}

var stuff = new my_class();

for (var i = 0; i < len; i++) {
  stuff.do_something(i)
}

它是如何工作的?

  1. do_something(i) 被调用
  2. this.get_data()do_something() 函数内部调用。
  3. get_data() 返回的promise 被解析后,继续执行到.then() 块。
  4. resolvedData 是来自 get_data() 承诺的解析值。
  5. 比较值,然后继续。

如您所见,这并没有考虑到即使对 stuff.do_something(i) 的调用尚未完成,for 循环也会继续。

您的问题不清楚您是允许它们全部并行运行(就像现在一样)还是需要它们按顺序运行。

如果你想知道是否所有调用都完成了,你可以让do_something()返回一个promise,然后使用Promise.all()等待它们全部解决,如下所示

function my_class() {
  this.do_something(data) {
    //Call the promise-returning function
    //Note that we return the same promise - no need to create a new one!
    return this.get_data()
      .then((resolvedData) => {
        //Wait for promise resolution
        //and compare the resolved value to 'data'
        if (resolvedData === data) {
          do_the_thing();
        }
      })
      .catch();
  }

  this.get_data = () => {
    return library.get_info(arguments);
  }
}

var stuff = new my_class();
//
var promises = [];
for (var i = 0; i < len; i++) {
  //Push each promise to the array
  promises.push(stuff.do_something(i));
}

Promise.all(promises)
  .then(() => {
    console.log("All promises have been resolved!")
  })
  .catch(() => {
    //Handle errors
  });

【讨论】:

【解决方案2】:

function my_class() {
    this.do_something( data ) {
          return new Promise(function(resolve,reject){
                this.get_data().then(function(dataReceiced){
                                    //reading promise retuned by    get_data();
              if(data == dataReceiced){
                  do_the_thing(); //need to promisify this also to use then();
                  resolve('Done');
              } else {   reject('Error'); }
                });  
           });
        }
    }

    this.get_data = function() {
        return library.get_info( arguments ); //can't do this, returns a promise
    }
}
i=0; // keep i global
var stuff = new my_class();

function doStuff(){
  if(i < len){ mainStuff(); }
}

function mainStuff(){
    stuff.do_something( i ).then(function(){
       i++; 
       doStuff();
    });

};
  doStuff(); // to start process. 

您需要承诺链中涉及的每个功能.. 像这样的..

不确定完整的场景,代码看起来像这样。

【讨论】:

  • 避免使用承诺构造函数反模式。在this.do_something 中,当不需要时,您不需要将对this.get_data() 的调用包装在promise 构造函数中
  • @atulquest93 “你需要承诺链中涉及的每个功能” 这就是我所害怕的……我想我希望有另一种解决方案。感谢您抽出宝贵时间提供帮助!
  • @Nate 在同一个链中使用异步和同步会产生很多边缘情况,请确保不要破坏代码。祝你好运
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2021-08-31
  • 1970-01-01
  • 1970-01-01
  • 2020-04-18
  • 1970-01-01
  • 2011-11-06
  • 1970-01-01
相关资源
最近更新 更多