我如何等待拉动?

How do I wait for a pull?

我需要从节点 运行 一个容器,所以我使用 dockerode 模块,它使用 Docker API。对于 运行 一个容器,我首先需要拉取图像(如果它在本地不存在)。为了简单起见,我已经 promisified 调用,但我很难弄清楚如何连接调用,特别是关于 pull 提供的回调。这是我拥有的:

init: function(opts) {
    var self = this;
    self.docker = new Docker();
    self.pull = Bluebird.promisify(
        self.docker.pull, { context: self.docker }
    );  
    self.createContainer = Bluebird.promisify(
        self.docker.createContainer, { context: self.docker }
    );  
},  

run: function(opts) {
    var self = this;
    return self.createContainer(opts).catch(function(e) {
        return self.pull(opts.Image).then(function(stream) {
            return self.createContainer(opts);
        }); 
    }).then(function(o) {;
        var start = Bluebird.promisify(
            o.start, { context: o } 
        );  
        return start({});
    }).then(function(o) {;
        var inspect = Bluebird.promisify(
            o.inspect, {context: o}
        );  
        return inspect();
    }); 
},  

所以发生的是第一个 createContainer 失败(因为图像尚未加载)并且发生了对 pull 的调用。成功后,将调用 createContainer

目前调用失败,因为图像还没有时间加载。我在文档中看到:https://github.com/apocas/dockerode(参见辅助函数)我可以做到:

        return self.pull(opts.Image).then(function(stream) {
            self.docker.modem.followProgress(stream, function(err, output) {
                return self.createContainer(opts);
            });
        }); 

...我认为这意味着 createContainer 只会在拉动完成时触发,但问题是我违背了诺言。正确的处理方式是什么?

TIA - e

* 已解决 *

根据下面 Joshua 的回答,这里是工作代码:

init: function(opts) {
    var self = this;
    self.docker = new Docker();
    self.pull = Bluebird.promisify(
        self.docker.pull, {context: self.docker}
    );  
    self.createContainer = Bluebird.promisify(
        self.docker.createContainer, {context: self.docker}
    );  
    self.followProgress = Bluebird.promisify(
        function(stream, done) {
            return self.docker.modem.followProgress(stream, done);
        },  
        {context: self.docker.modem}
    );  
},  
run: function(opts) {
    var self = this;
    return self.createContainer(opts).catch(function(e) {
        return self.pull(opts.Image).then(function(stream) {
            return self.followProgress(stream);
        }).then(function() {
            return self.createContainer(opts);
        }); 
    }).then(function(o) {
        var start = Bluebird.promisify(
            o.start, {context: o}
        );  
        start();
        return o;
    }).then(function(o) {;
        var inspect = Bluebird.promisify(
            o.inspect, {context: o}
        );
        return inspect();
    });
},

我只是不高兴 start() 的结果丢失了但是如果我想在 运行ning 之后检查我需要 o 但我不知道如何处理两者。但上面的作品

泛泛而谈,假设你有:

return createsPromiseA().then((a) => {
  takesNodebackB(a, (err, b) => {
    let promiseC = createsPromiseC();
    // How do I return promiseC??
  });
});

有2个答案。一个使用原生承诺 ootb:

return createsPromiseA().then((a) => {
  return new Promise((resolve, reject) => {
    takesNodebackB(a, (err, b) => {
      if (err) return reject(err);
      resolve(b);
    });
  });
}).then((b) => createsPromiseC());

这里的技巧是将 nodeback 函数包装在一个 promise 中。

第二个答案是 bluebird 附带 http://bluebirdjs.com/docs/api/promise.promisify.html,虽然我没有使用它,但 应该 允许你做同样的事情,比如:

return createsPromiseA()
  .then((a) => bluebird.promisify(takesNodebackB)(a))
  .then((b) => createsPromiseC());