2017-08-06 377 views
0

我正在使用dockerode來從node.js中操作docker。它自己的圖書館不是問題,但我與PROMISE有問題。看起來承諾不等待解決。Node.JS - 承諾不會等待解決

下面的代碼我預期的結果應該是:

Start 
Middle // (or Err if docker does not running) 
End 

但我收到:

Start 
End 
Middle 

似乎承諾不等待繼續的JavaScript運行流程。我做錯了什麼?

const Docker = require('dockerode') 
let docker = new Docker(); 

console.log('Start'); 
let promise = new Promise(function (resolve, reject) { 
    docker.listContainers({all: true}, function (err, data) { 
     if (err) { 
      reject(err) 
     } else { 
      resolve(data); 
     } 
    }); 
}); 

promise.then(function (data) { 
    console.log('Middle'); 
}, function (err) { 
    console.log('Err'); 
}); 

console.log('End'); 

複製並粘貼代碼上https://npm.runkit.com/dockerode或在這裏看到的結果是:https://runkit.com/embed/y3wvg6ktecb9

+0

在'promise.then'之前加上'await'(並將所有東西包裝在'async function'中)。 – 2017-08-06 22:48:40

+0

這就是一個承諾如何工作......解決什麼時候準備好,這可能是你的兩個同步console.log()之後的幾年... – WilomGfx

+0

@torazaburo沒有必要,這只是承諾的語法糖。 – WilomGfx

回答

6

你的輸出是正確的,你誤解的承諾是如何工作的。

承諾是asynchronous,它們在事件循環中的different (microtask) tick上運行。這意味着在同步代碼運行時沒有解決諾言。

// output 'a', 'c', 'b' 
 
console.log('a'); 
 
Promise.resolve().then(() => console.log('b')); 
 
console.log('c');

此外,即使承諾是同步的,調用docker.listContainers是異步接收回調也不會被調用,直到下一個節拍。

如果你想等待一個承諾,要麼把你想要一個承諾是在then回調承諾解決後,運行該代碼:

// output 'a', 'b', 'c' 
 
console.log('a'); 
 
Promise.resolve() 
 
    .then(() => console.log('b')) 
 
    .then(() => console.log('c'));

或包裹

// output 'a', 'b', 'c' 
 
(async() => { 
 
    console.log('a'); 
 
    await Promise.resolve().then(() => console.log('b')) 
 
    console.log('c'); 
 
})()
0:你在 async functionawait承諾碼

+0

我不知道爲什麼這被拒絕,但迄今爲止它是最好的答案。 – WilomGfx

+1

@WilomGfx哈哈不知道我的朋友,有時程序員只是無端的脾氣暴躁:) – nem035

+1

這是正確的答案,很好的解釋 –