簡體   English   中英

為什么第27行在第24行之前執行?

[英]Why line 27 is executed before line 24?

我初學javascript並嘗試構建一個干凈的對象,以便在我的用例中使用Dockerode庫。 我有一個異步問題,我的第27行在24之前執行,我不明白為什么以及如何解決它!

此外,如果您更容易,請訪問此公開要點: https//gist.github.com/msitruk/2cdb655a0bebdb29c61d8bc5606a2695

const Docker = require('dockerode');
const docker = new Docker({
    socketPath: '/var/run/docker.sock'
});

// CONSTRUCTOR
function SearchUtils() {
    this.listContainersPromise = docker.listContainers({all: true});
    this.scraperListId = [];
}

// "METHODS"
SearchUtils.prototype.run = function() {
    this.getScraperContainersListPromise()
        .then((containers) => {
            for (let i = 0; i < containers.length; i++) {
                if (containers[i].Names.toString().indexOf("scraper") !== -1) {
                    this.addToScraperList(containers[i].Id, "wait");
                }
            }
        }, (err)=>{console.log(err)})
        .then(()=>{
            this.checkReadyScraper();
        },(err)=>{console.log(err)})
        .then(() => {
            this.scrap();
        }, (err)=>{console.log(err)});
};

SearchUtils.prototype.checkReadyScraper = function() {
    for (let i = 0; i < this.scraperListId.length; i++) {
        this.exec("getStatus", this.scraperListId[i].id);
    }
};

SearchUtils.prototype.getScraperContainersListPromise = function() {
    return this.listContainersPromise; // <- Not working
};

SearchUtils.prototype.exec = function(type, containerId){
    let container = docker.getContainer(containerId);
    if (type === "getStatus"){
        this.runExec(container, 'cat /home/immobot/status');
    }
    else if (type === "scrap") {
        this.runExec(container, 'torify scrapy crawl seloger -o seloger.json');
    }
};

SearchUtils.prototype.scrap = function() {
    let localRdyScraperList = [];
    for (let i = 0; i < this.scraperListId.length; i++) {
        if(this.scraperListId[i].status.toString('utf8').indexOf("ready") !== -1){
            localRdyScraperList.push(this.scraperListId[i].id);
        }
    }
    console.log("test de localRdyScraperList : "+localRdyScraperList);
    // this.exec("scrap", this.scraperListId[i].id);
};

SearchUtils.prototype.addToScraperList = function(containerId,status) {
    this.scraperListId.push({id: containerId, status: status});
};

SearchUtils.prototype.getScraperList = function() {
    return this.scraperListId;
};

SearchUtils.prototype.getScraperList = function() {
    return this.scraperListId;
};

SearchUtils.prototype.runExec = function (container, cmd) {
    let options = {
        Cmd: [ '/bin/bash', '-c', cmd ],
        AttachStdout: true,
        AttachStderr: true
    };

    container.exec(options, (err, exec) => {
        if (err) return;
        exec.start((err, stream) => {
            if (err){
                console.log("error : "+err);
                return;
            }

            // container.modem.demuxStream(stream, process.stdout, process.stderr)

            if (cmd === "cat /home/immobot/status"){
                let newStream = require('stream');
                let logStream = new newStream.PassThrough();
                logStream.on('data', (chunk) => {
                    // console.log(chunk.toString('utf8'));
                    if (chunk.toString('utf8').indexOf("ready") !== -1){
                        console.log("CONTAINER READY !!");
                        //EDIT CONTAINER STATUS IN SCRAPERLIST TO READY
                        this.changeStatusToReady(container.id);
                    }
                });
                container.modem.demuxStream(stream, logStream, process.stderr);

            }
            else if (cmd === "torify scrapy crawl seloger -o seloger.json"){
                console.log("on lance le scrape sur un des scraper rdy");
                container.modem.demuxStream(stream, process.stdout, process.stderr)
            }

            // container.modem.demuxStream(stream, logStream, process.stderr);

            exec.inspect(function(err, data) {
                if (err){
                    console.log("error : "+err);
                    return;
                }
            });
        });
    });
};

SearchUtils.prototype.changeStatusToReady = function (containerId){
    for (let i = 0; i < this.scraperListId.length; i++) {
        if(this.scraperListId[i].id === containerId){
            this.scraperListId[i].status = "ready";
        }
    }
    // console.log(this.getScraperList());
};

module.exports = SearchUtils;

如果你的鏈接承諾,不要忘記返回你的下一個承諾..

例如..

.then(()=>{
  this.checkReadyScraper();
}

如果checkReadyScraper()是一個promise,那么你會想要返回它。

例如。

.then(()=>{
  return this.checkReadyScraper();
}

否則你所做的就是運行checkReadyScraper()並完全忽略返回的Promise。

以下是我認為你的runExec看起來如何。 我假設exec.inspect是你要解決的問題。

 SearchUtils.prototype.runExec = function (container, cmd) { return new Promise ((resolve, reject)=>{ let options = { Cmd: [ '/bin/bash', '-c', cmd ], AttachStdout: true, AttachStderr: true }; container.exec(options, (err, exec) => { if (err) return reject(err); //return error exec.start((err, stream) => { if (err){ console.log("error : "+err); return reject(err); //return error } // container.modem.demuxStream(stream, process.stdout, process.stderr) if (cmd === "cat /home/immobot/status"){ let newStream = require('stream'); let logStream = new newStream.PassThrough(); logStream.on('data', (chunk) => { // console.log(chunk.toString('utf8')); if (chunk.toString('utf8').indexOf("ready") !== -1){ console.log("CONTAINER READY !!"); //EDIT CONTAINER STATUS IN SCRAPERLIST TO READY this.changeStatusToReady(container.id); } }); container.modem.demuxStream(stream, logStream, process.stderr); } else if (cmd === "torify scrapy crawl seloger -o seloger.json"){ console.log("on lance le scrape sur un des scraper rdy"); container.modem.demuxStream(stream, process.stdout, process.stderr) } // container.modem.demuxStream(stream, logStream, process.stderr); exec.inspect(function(err, data) { if (err){ console.log("error : "+err); //don't forget to return the rejection return reject(err); } //looks like everything was ok, lets resolve resolve(data); }); }); }); //resolve("ok"); too early // TODO ADD EROR STRATEGY //reject("error"), pointless }); }; 

執行任務(使用container.exec,在代碼中的第81行),從其余步驟開始異步運行,完成后進行回調。 如果訂單很重要,您必須確保在運行scrap命令之前完成刮刀的所有檢查。

首先 - 不需要在每次then()調用中處理錯誤。 您可以實現單個錯誤捕獲,它將捕獲序列中任何then()項中的錯誤:

.then(()=> {
  this.checkReadyScraper();
})
.then(() => {
  this.scrap();
})
.catch(e => console.log(e))

另請注意,像catch(e => console.log(e))這樣的箭頭函數不需要{}和;

您的問題是您的任務是異步。 如果你想鏈接任務 - 你應該做一個任務來返回一個Promise

這是你應該重構的一個粗略的例子:

//Should return Promise
SearchUtils.prototype.exec = function(type, containerId){
  let container = docker.getContainer(containerId);
  if (type === "getStatus"){
    //runExec should return us a Promise
    return this.runExec(container, 'cat /home/immobot/status');
  }
  else if (type === "scrap") {
    return this.runExec(container, 'torify scrapy crawl seloger -o seloger.json');
  }
};

SearchUtils.prototype.runExec = function (container, cmd) {
  return new Promise(function(resolve, reject) {
     //do some stuff
     //then call resolve(result)
     //or call reject(error)
  });
}

在此之后,你將能夠鏈接Promises(這實際上非常棒,並有助於解決回調地獄):

.then(()=> {
  //this not returns Promise, and it will be correctly chained 
  return this.checkReadyScraper();
})
.then(() => {
  //this not returns Promise, and it will be correctly chained
  return this.scrap();
})
.catch(e => console.log(e))

另外,為了使這看起來更干凈,我甚至建議做一些小的重構,最終會給你oneliner:

.then(this.checkReadyScraper).then(this.scrap).catch(console.log)

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM