Javascript 尝试在执行函数后读取节点js创建的目录

Javascript 尝试在执行函数后读取节点js创建的目录,javascript,node.js,Javascript,Node.js,我创建了一个节点应用程序,它可以删除google并下载前15个图像,然后将其存储在HDD中的一个文件夹中,该文件夹是压缩后收到的查询。现在我面临的问题是,当我使用readdirSync返回读取文件夹并错误存储结果时,它返回一个空数组,代码有什么问题 request(url, function (error, response, body) { if (!error) { var $ = cheerio.load(body); var imgNodes = $('#ires td a i

我创建了一个节点应用程序,它可以删除google并下载前15个图像,然后将其存储在HDD中的一个文件夹中,该文件夹是压缩后收到的查询。现在我面临的问题是,当我使用readdirSync返回读取文件夹并错误存储结果时,它返回一个空数组,代码有什么问题

 request(url, function (error, response, body) {
if (!error) {
var $ = cheerio.load(body);
    var imgNodes = $('#ires td a img');
    // imgNodes is merely an array-like object, sigh.
    // This is purposedly old-school JS because newer stuff doesn't work:
    var urls = [];
    for(let i = 0; i <= 14; i++){
        let imgNode = imgNodes[i];
        urls.push(imgNode.attribs['src']);
    }  
// console.log(urls);

const processCompress = new Promise(resolve => {
    fs.mkdir(path.join(__dirname,'Photos',query), function (error) {
    let j = 0;
     if(!error){
        for(i in urls){
            console.log(i);
            var source = tinify.fromUrl(urls[i]);
            source.toFile(path.join(__dirname,'Photos', query,"optimized_"+ ++j +".jpg"));
        }
    }});
    resolve();
});

const getFiles = new Promise(resolve => {
    fs.readdirSync(path.join(__dirname,'Photos', query)).forEach(function (file) {
        fileName.push(path.join(__dirname,'Photos',query,file));
    });
    resolve();
});

function colourMeBw(){
    for(let k = 0; k < fileName.length; k++){
    Jimp.read(fileName[k], (err, image) => {
        if (err) throw err;
        image.greyscale().write(fileName[k]);
    });
}}
processCompress.then(() => getFiles);
colourMeBw(); 
 } else {
console.log("We’ve encountered an error: " + error);
 }
请求(url、函数(错误、响应、正文){
如果(!错误){
var$=总负荷(车身);
变量imgNodes=$('ires td a img');
//imgNodes只是一个数组状的对象,叹气。
//这是老派JS,因为新的东西不起作用:
var url=[];
for(设i=0;i{
mkdir(path.join(uuu dirname,'Photos',query),函数(error){
设j=0;
如果(!错误){
对于(URL中的i){
控制台日志(i);
var source=tinify.fromUrl(URL[i]);
toFile(path.join(uu dirname,'Photos',query,“optimized_u+++j++.jpg”);
}
}});
解决();
});
const getFiles=新承诺(解析=>{
fs.readdirSync(path.join(uu dirname,'Photos',query)).forEach(函数(文件){
push(path.join(_dirname,'Photos',query,file));
});
解决();
});
函数colormebw(){
for(设k=0;k{
如果(错误)抛出错误;
image.greyscale().write(文件名[k]);
});
}}
processCompress.then(()=>getFiles);
colormebw();
}否则{
log(“我们遇到了一个错误:“+错误”);
}
我认为直接在fs.mkdir之后调用resolve()是错误的,因为mkdir是以NYC的方式工作的,所以在不执行mkdir的全部工作的情况下就实现了解析

const processCompress = new Promise(resolve => {
            fs.mkdir(path.join(__dirname, 'Photos', query), function(error) {
                let j = 0;
                if (!error) {
                    for (i in urls) {
                        console.log(i);
                        var source = tinify.fromUrl(urls[i]);
                        source.toFile(path.join(__dirname, 'Photos', query, "optimized_" + ++j + ".jpg"));
                    }
                }

                resolve(); // <---- inside callback from mkdir.
            });
            // call the resolve from inside the mkDirs-callback function
            // resolve();
        });  
constprocesscompress=新承诺(解析=>{
fs.mkdir(path.join(uu dirname,'Photos',query),函数(错误){
设j=0;
如果(!错误){
对于(URL中的i){
控制台日志(i);
var source=tinify.fromUrl(URL[i]);
toFile(path.join(uu dirname,'Photos',query,“optimized_u+++j++.jpg”);
}
}

resolve();//我阅读了代码,我认为您要做的是这样的:

const cheerio = require("cheerio");
const fetch = require("node-fetch");
const tinify = require("tinify");
const fs = require("fs");
const path = require("path");

const getImages = url => {
  return fetch(url)
    .then(responseToText)
    .then(bodyToImageUrls)
    .then(makePhotoDirectory)
    .then(downloadFiles)
    .then(processImageData)
    .then(doImageManipulation)
    .catch(error => {
      console.log("We’ve encountered an error: " + error);
    });
};

const responseToText = res => res.text();

const bodyToImageUrls = body => {
  const $ = cheerio.load(body);
  return $("img").attr("src");
};

const imgNodesToUrls = imgNodes => {
  return imgNodes.map(imgNode => imgNode.name);
};

const makePhotoDirectory = urls => {
  const dir = path.join(__dirname, "Photos");

  if (!fs.existsSync(dir)) {
    fs.mkdirSync(dir);
  }

  return urls;
};

const downloadFiles = urls => {
  /* 
    I could not run this since I don't have a Tinify API key
    but I assume that it returns a promise.
  */
  const promises = urls.map(url => tinify.fromUrl(url));
  return Promise.all(promises);
};

const processImageData = imageData => {
  const promises = imageData.map((data, i) => {
    const fileUrl = path.join(__dirname, "Photos", `optimized_${i}.jpg`);
    return data.toFile(fileUrl);
  });

  return Promise.all(promises);
};

const doImageManipulation = images => {
  // Add your image manipulation here
};

您的代码有很多错误:

  • processCompress()
    中,您要在
    fs.mkdir()
    完成之前以及在获取和写入任何图像之前解析承诺

  • getFiles()
    中,您正在将同步I/O函数包装在承诺中。第一个问题是您根本不应该使用同步I/O。这是破坏服务器可伸缩性的最快方法。然后,一旦切换到异步版本的
    fs.readdir()
    ,您必须适当地解决承诺问题

  • 无法知道
    colormebw()
    何时实际完成

  • 由于各种原因,您不应使用
    for(url中的i)
    迭代数组。在ES6中,您可以使用
    for(url的url)
    。在ES5中,您可以使用传统的
    for(var i=0;i
    url.forEach()

  • 你没有错误传播。如果你在中间某个地方出错,整个过程会哽咽,因为即使进程已经失败,进程的后续部分仍会继续尝试工作。调用方无法知道发生了什么错误。

  • 没有办法知道什么时候一切都完成了

  • 这里有一个版本的代码,它使用承诺来正确地排序事情,适当地传播所有错误,并告诉您什么时候一切都完成了。我自己不知道
    tinify
    Jimp
    库,所以我查阅了它们的文档,看看如何将它们与承诺一起使用(两者似乎都内置了承诺支持)。我使用Bluebird promise库为
    fs
    库提供promise支持,并利用
    promise.map()
    这一点在这里很方便

    如果您不想使用Bluebird promise库,您可以通过其他方式promisify
    fs
    模块或事件promisify您希望用于promises的单个
    fs
    方法。但一旦您习惯了使用promise进行异步编程,您将希望将其用于所有
    fs
    工作

    这显然是未经测试的(在这里无法运行),但希望您了解我们正在尝试做的事情的总体思路

    const Promise = require('bluebird');
    const fs = Promise.promisifyAll(require('fs'));
    const Jimp = require('jimp');
    const rp = require('request-promise');
    
    rp(url).then(function(body) {
        var $ = cheerio.load(body);
        var imgNodes = $('#ires td a img');
        // imgNodes is merely an array-like object, sigh.
        // This is purposedly old-school JS because newer stuff doesn't work:
        var urls = [];
        for (let i = 0; i <= 14; i++) {
            let imgNode = imgNodes[i];
            urls.push(imgNode.attribs['src']);
        }
        // console.log(urls);
    
        const processCompress = function() {
            return fs.mkdirAsync(path.join(__dirname, 'Photos', query).then(function(error) {
                let j = 0;
                return Promise.map(urls, function(url) {
                    var source = tinify.fromUrl(url);
                    return source.toFile(path.join(__dirname, 'Photos', query, "optimized_" + ++j + ".jpg"));
                });
            });
        });
    
        const getFiles = function() {
            return fs.readdirAsync(path.join(__dirname, 'Photos', query).then(function(files) {
                return files.map(function(file) {
                    return path.join(__dirname, 'Photos', query, file);
                });
            });
        };
    
        function colourMeBw(fileList) {
            return Promise.map(fileList, function(file) {
                return Jimp.read(file).greyscale().write(file);
            });
        }
        return processCompress().then(getFiles).then(colourMeBw);
    }).then(function() {
        // all done here
    }).catch(function(err) {
        // error here
    });
    
    const Promise=require('bluebird');
    const fs=promisifyAll(require('fs'));
    const Jimp=require('Jimp');
    const rp=要求(“请求-承诺”);
    rp(url)。然后(函数(主体){
    var$=总负荷(车身);
    变量imgNodes=$('ires td a img');
    //imgNodes只是一个数组状的对象,叹气。
    //这是老派JS,因为新的东西不起作用:
    var url=[];
    
    对于(让我=0;我喜欢你解释核心问题的第一句话。但是,撕毁承诺在编程生活中正在倒退。@jfriend00你使用承诺是对的,所以我编辑了我的帖子并删除了异步npm部分。你提出的答案只是这里需要解决的问题的一小部分。你在这里收到了很多答案,但从来没有收到过提供了关于其中任何一个的任何反馈。这不是本网站的实际工作方式。请评估您收到的答案,如果您有任何问题,请提出问题,如果您的问题得到回答,请接受最佳答案。这是一个互动网站。您提出问题,我们提供答案,您提供答案的反馈,希望您能参与活动当你的问题得到回答时,你通常会接受一个问题(通过单击旁边的复选标记)。提出一个问题然后消失而没有反馈是不正确的