【问题标题】:Returning a single resolve() from a loop从循环中返回单个 resolve()
【发布时间】:2019-12-20 14:33:48
【问题描述】:

我写了下面的代码sn-p:

var data = require('./readFile.js');
const argv = require('./index.js');
const colors = require('colors');
const rp = require('request-promise').defaults({ encoding: null });
const memeImage = argv.name;
const path = './json/meme.json';

var myData;

data.readFile(path)
.then(function (value) {
    var jsonData = JSON.parse(value);

    const options = {
        resolveWithFullResponse: true
    }
    jsonData.forEach(element => {
        if(element.title == memeImage) {
            rp.get(element.image, options)
            .then(function(response){
                if(response.statusCode == 200) {
                    myData = Buffer.from(response.body).toString('base64');
                    myData.replace('myData:image/png;base64,', '');
                    console.log(myData);

                    resolve(myData);
                }
                else {
                    console.log('Error in retrieving image.  Status code: ', response.statusCode);
                    reject('Error in retrieving image.');
                }
            })
            .catch(function(error){
                console.log('Error in downloading the image via request()');
                reject('Error in downloading the image via request()');
            });
        }
    });
})
.then(function(myData) {
    console.log(myData);
})
.catch(function(err) {
    //Error in reading the file
    console.log(err);
})

module.exports=myData;

这里,从另一个文件 (readFile.js) 导入的函数 readFile() 返回了一个承诺。 readFile.js如下:

var myData, obj, found=false;

function readFile(path) {
    return new Promise(function(resolve, reject){
        if(!fs.existsSync(path)) {
            console.log('Will throw error now!');
            reject("memes.json file does not exist");
        }
        else {
            //File exists
            console.log('File found');
            var data = fs.readFileSync(path, 'utf8');
            resolve(data);
        }
    })
}

module.exports.readFile = readFile;

现在在最上面的代码 sn-p 中,我的目标是使用 readFile.js 文件读取文件(将标题映射到 URL),然后在相应的 URL 下载图像。一旦找到这个匹配项(上面的 if 子句),promise 应该被解析并返回到一个新模块。

现在发生的是,我得到以下输出:

node ./lib/getImage.js -n title -t topText -b bottomText
找到文件
未定义
<...>
通过 request() 下载图像时出错
未处理的拒绝 ReferenceError: 拒绝未定义 ...

我的问题是,thisthis 之类的答案都是关于从循环中返回多个承诺。就我而言,我只想返回一个 promise resolve(取决于匹配)然后停止。

我如何做到这一点?

谢谢!

【问题讨论】:

    标签: javascript node.js promise


    【解决方案1】:

    您不能只是在 .then() 处理程序中盲目地调用 resolve()reject()。这些函数仅在手动创建的 Promise 中定义,因此它们不存在于您的上下文中。

    如果你想在.then() 处理程序中设置解析值,那么只需return 那个值。如果你想在 .then() 处理程序中拒绝,那么 throw someErrreturn 被拒绝的承诺。

    如果您在 .forEach() 回调中,并且想要停止进一步处理并设置父 Promise 的已解析值,则不能。你在一个回调函数内部,所以你不能直接从外部函数return.forEach() 没有办法停止它的迭代。相反,使用常规的for 循环,然后你可以只用return value 来结束for 循环迭代并建立你的承诺链的解析值。与 .forEach() 循环相比,常规的 for 循环可以让您对程序流进行更多的控制。

    仅供参考,Unhandled rejection ReferenceError: 是由尝试调用不存在的 reject() 函数在 .catch() 内部创建异常引起的。删除它。如果你想记录并保持被拒绝的承诺,那么throw

    然后,如果您在 for 循环中使用 rp.get(),您将需要将其与 awaitPromise.all() 一起使用,以便知道一切何时完成。

    【讨论】:

    • 哦,但是我确实有一个 .catch() 对应于 console.log('Error in download the image via request()'); 这与 @987654346 有关@,不是吗?
    • 并且,您能否详细说明一下与 .forEach() 循环相比,常规的 for 循环可以让您对程序流程有更多的控制
    • @J.Doe - 是的,我没有看到,因为你的编码风格不同。但是发生错误是因为您在 .catch()reject('Error in downloading the image via request()'); 中创建了另一个错误,之后没有 .catch() 来捕获该新错误。当然,您不想要另一个 .catch() - 只需删除拒绝即可。
    • @J.Doe - 使用常规的for 循环,您可以通过returnbreak 停止迭代。使用.forEach() 无法停止迭代。在.then() 处理程序中使用for 循环,您可以使用return someValue 完成.then() 处理程序并设置承诺链的解析值并停止循环。在 .forEach() 回调中,您不能执行其中任何一项,因为从 .forEach() 回调中返回只会完成该迭代,而 .forEach() 循环只会继续前进。
    • @J.Doe - 坦率地说,for/of 和现代 Javascript 中的块范围,我几乎没有理由再使用 .forEach()。这只是额外的开销和编码复杂性,几乎没有什么好处。
    猜你喜欢
    • 2018-08-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-10-25
    • 2015-11-09
    • 2019-07-31
    • 2014-04-22
    • 1970-01-01
    相关资源
    最近更新 更多