javascript - 模块化 Promise 和 Promise.all()

标签 javascript design-patterns promise es6-promise

我有一堆函数返回我想要泛化的 promise ,所以我这样写它们:

function checkWebpageForReference(data){
    //checks a webpage for the reference in html
    var promise = new Promise(function(resolve,reject){
        fetchUrl(data.url, function(err, meta, body){
            if (err) { reject(err); } else {
                console.log(body)
                if (body.toString().indexOf(data.text) !== -1){
                    resolve(data);
                } else {
                    reject("Could not find quote");
                }
            }
        });
    });
    return promise;
}

function takeScreenshot(data){
    //takes a screenshot of a webpage and saves it to the file system
    //TODO: Mouse coordinates
    data.id = shortid.generate();
    data.filename = data.id+'.png';
    var promise = new Promise(function(resolve,reject){
        webshot(data.url, data.filename, { shotOffset: {left: data.mouseX, top: data.mouseY} }, function(err) {
            if (err) { reject(err); } else {
                resolve(data);   
            }
        });
    });
    return promise;
}

function uploadReferencePictureToS3(data){
    //uploads a picture to S3
    var promise = new Promise(function(resolve, reject){
        s3.putObject({
            ACL: 'public-read',
            Bucket: S3_BUCKET,
            Key: data.id,
            Body: data.picturedata,
            ContentType: "image/jpg"
        }, function(err) {
            if (err) { reject(err); } else {
                resolve(data);   
            }
        }); 
    });
    return promise;
}

function saveNewReferenceToDb(data){
    //saves a new Reference to the database
    var promise = new Promise(function(resolve, reject){
        new Reference({
            _id: data.id,
            url: data.url,
            text: data.text,
            screenshot_url: AWS_S3_URL + data.id,
            created_by: "Daniel"
        }).save(function(err, saved){
            if (err) { reject(err); } else {
                data.newReference = saved;
                resolve(data);   
            }
        });
    });
    return promise;
}

function readFile(data){
    //reads a file from the file structure and stores it in a variable
    var promise = new Promise(function(resolve,reject){
        console.log(data);
        fs.readFile(data.filename, function(err, picturedata){
            console.log(picturedata);
            if (err) { reject(err); } else {
                data.picturedata = picturedata;
                resolve(data);   
            }
        }) ;
    });
    return promise;
}

function deleteFile(data){
    //deletes a file from the file structure
    var promise = new Promise(function(resolve, reject){
        fs.unlink(data.filename);
        resolve(data);
    });
    return promise;
}

我解析每个函数中的数据,因为我计划拥有很多此类函数,并且我不知道链接时调用它们的顺序:

readfile(somedata)
.then(upload)
.then(delete)
.then(save)
//etc

在我必须执行 Promise.all 之前,这一切都很好:

   Promise.all([
        referenceTools.checkWebpageForReference(req.body),
        referenceTools.takeScreenshot(req.body)
    ])
    .then(function(results){
        utils.readFile(results[1])
        .then(referenceTools.uploadReferencePictureToS3)
        .then(utils.deleteFile)
        .then(referenceTools.saveNewReferenceToDb)
        .then(function(data){
            res.json(data.newReference);
        })
        .catch(function(err){
            utils.errorHandler(err);
            res.send("There was an internal error. Please try again soon.");
        });  
    })
    .catch(function(err){
        utils.errorHandler(err);
        res.send("There was an internal error. Please try again soon.");
    });
    //my very ugly way of doing it

使用Promise.all().then(upload)给我错误,因为 Promise.all() 返回的新 promise 是一个包含来自 checkWebpageForReference 的两个分辨率的对象和takeScreenshot 。本质上,在 readFile ,我无法访问data字段,因为结果 promise 是 [data, data] .

是否有一个我可以遵循的模式来帮助我实现我需要做的事情?我需要将 promise 模块化,为他们提供尽可能多的数据。

最佳答案

你可以像这样 .map() 覆盖它们:

Promise.all(...)
  .then(datas => Promise.all(datas.map(upload)));

由于您位于服务器端,因此我强烈推荐 Bluebird 作为 native Promises 的直接替代品。然后你可以这样做:

Promise.all(...)
  .map(upload);

关于javascript - 模块化 Promise 和 Promise.all(),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41841763/

相关文章:

具有用于数据库访问的 API 的 Python 应用程序

design-patterns - oop中的多对多关系

java - 空对象模式与新对象

node.js - getById() 返回未定义的 Promise

javascript - Ionic Error Object(...) 不是 NativePageTransitions.fade 中的函数

javascript - 我如何以编程方式检测浏览器如何处理 window.close()?

javascript - 为什么 Promise 会捕获语法错误?

javascript - Promise.all 中的链式 promise ,没有包装器 Promise

javascript - 使用 js : order <tr> and <td> 创建表的问题

javascript - 遍历(可能无限)重复的对象结构