2017-01-22 130 views
0

我想創建一個例子來理解Promise().then()。 我創建了一個需要時間並且必須同步完成操作的操作。 該代碼是下面:Javascript Promise/Then Example

// 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 

感謝您的幫助。

回答

2

你必須調用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); 
 
});

1

我認爲這裏的主要問題是您的異步​​行爲(setTimeout)未涉及您的承諾鏈。

resolve(null)longOperation(id)之後將立即返回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 PromiselongOperation的內部,當setTimeout回調只能處理解決。

1

的一個問題是這兩條線:

longOperation(id); 
resolve(null); 

因爲longOperation是一個異步功能,resolve(null)運行之前longOperation結束運行。

我將結合前兩個功能,以確保承諾不能解決直到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這樣的內置功能,如果您使用承諾,那麼您應該能夠避免使用回調。