【问题标题】:Javascript Promise/Then ExampleJavascript Promise/Then 示例
【发布时间】:2017-01-22 15:44:23
【问题描述】:

我想创建一个示例来了解Promise().then()。 我创建了一个需要时间并且必须同步完成的操作。 代码如下:

// Example: long operation that takes time to execute
var longOperation = function(id) {

    var time = 1000 * Math.random();

    console.log('[' + id + '] Operation started for: ' + time + 'ms');

    setTimeout(function(err) {
        console.log('[' + id + '] Completed operation:   ' + time + 'ms');
        var count = id * 10;
    }, 1000 * Math.random());

};

// Create new promise for longOperation
var longOpPromise = function(id) {

    return new Promise(function(resolve, reject) {
        longOperation(id);
        resolve(null);
    });

};

// Create sequencing
var runLongOperation = function(callback) {

    var count1;

    longOpPromise(1).then(function(count) {

        count1 = count;
        console.log('Count 1: ' + count1);

        longOpPromise(2).then(function(count2) {
            console.log('Count 2: ' + count2);
            callback(null, count1, count2);
        });

    });

};

// Run
runLongOperation(function(err, count1, count2) {
    if (err) console.error(err);
    console.log('Count 1 ' + count1 + ' | Count 2: ' + count2);
});

运行结果:

    **** Output ****
    [1] Operation started for: 626.77225866355ms
    [1] Completed operation:   626.77225866355ms

then() 中的方法不执行,回调也不执行。也许计数没有得到解决。

如果我将其更改为resolve(null),这些会执行但不按顺序执行:

    **** Output ****
    [1] Operation started for: 435.5367429088801ms
    Count 1: null // This should come after [1] is completed
    [2] Operation started for: 256.17250707000494ms
    Count 2: null // This should come after [2] is completed
    Count 1 null | Count 2: null // This should come after [2] is completed
    [2] Completed operation:   256.17250707000494ms
    [1] Completed operation:   435.5367429088801ms

感谢您的帮助。

【问题讨论】:

    标签: javascript


    【解决方案1】:

    您必须在异步操作完成时调用resolve

    使用此代码:

    longOperation(id);
    resolve(null);
    

    您正在开始异步操作,然后立即解决承诺。


    如果要将count 的值传递给then 函数,则需要在调用resolve() 时传递它。目前你正在通过null


    此版本的代码将其修改为将 resolve 作为回调传递,并且仅在正确的时间调用它。

    // Example: long operation that takes time to execute
    var longOperation = function(id, resolve) {
      var time = 1000 * Math.random();
      console.log('[' + id + '] Operation started for: ' + time + 'ms');
    
      setTimeout(function(err) {
        console.log('[' + id + '] Completed operation:   ' + time + 'ms');
        var count = id * 10;
        resolve(count);
      }, 1000 * Math.random());
    };
    
    // Create new promise for longOperation
    var longOpPromise = function(id) {
      return new Promise(function(resolve, reject) {
        longOperation(id, resolve);
      });
    };
    
    // Create sequencing
    var runLongOperation = function(callback) {
      var count1;
      longOpPromise(1).then(function(count) {
        count1 = count;
        console.log('Count 1: ' + count1);
    
        longOpPromise(2).then(function(count2) {
          console.log('Count 2: ' + count2);
          callback(null, count1, count2);
        });
      });
    };
    
    // Run
    runLongOperation(function(err, count1, count2) {
      if (err) console.error(err);
      console.log('Count 1 ' + count1 + ' | Count 2: ' + count2);
    });

    【讨论】:

      【解决方案2】:

      我认为这里的主要问题是您的异步​​操作 (setTimeout) 不涉及您的承诺链。

      longOperation(id) 之后的resolve(null) 将立即返回 null 而不会等待 longOperation 函数完成其超时间隔。

      这样的事情会起作用:

      // Example: long operation that takes time to execute
      var longOperation = function(id) {
      
          var time = 1000 * Math.random();
      
          console.log('[' + id + '] Operation started for: ' + time + 'ms');
      
          return new Promise(function(resolve) {
              setTimeout(function(err) {
                  console.log('[' + id + '] Completed operation:   ' + time + 'ms');
                  var count = id * 10;
                  resolve(count);
              }, time);
          });
      
      };
      
      // Create new promise for longOperation
      var longOpPromise = function(id) {
          return longOperation(id);
      };
      

      我将new Promise 移动到longOperation 内部,并且仅在处理setTimeout 回调时才解析。

      【讨论】:

        【解决方案3】:

        一个问题是这两行:

        longOperation(id);
        resolve(null);
        

        因为longOperation 是一个异步函数,所以resolve(null) 将在longOperation 完成运行之前运行。

        我会结合前两个函数来确保 promise 不会解决,直到 setTimeout 中的回调运行:

        var longOpPromise = function(id) {
        
            var time = 1000 * Math.random();
        
            console.log('[' + id + '] Operation started for: ' + time + 'ms');
        
            return new Promise(function(resolve, reject) {
                setTimeout(function(err) {
                    console.log('[' + id + '] Completed operation:   ' + time + 'ms');
                    var count = id * 10;
                    resolve() // Now the promise won't resolve until here.
                }, 1000 * Math.random());
            })
        
        
        };
        

        我也会避免像你那样混合回调和承诺 - 除了像 setTimeout 这样的内置函数,如果你使用承诺,那么你应该能够避免使用回调。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2021-04-18
          • 2019-01-12
          • 1970-01-01
          • 1970-01-01
          • 2018-12-31
          • 2016-10-18
          相关资源
          最近更新 更多