簡體   English   中英

模塊化承諾和Promise.all()

[英]Modular promises and Promise.all()

我有一堆函數返回我希望進行泛化的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()返回的新承諾是一個包含來自checkWebpageForReferencetakeScreenshot分辨率的對象。 本質上,在readFile ,我無法訪問data字段,因為生成的promise是[data, data]

是否有一種模式可以幫助我實現我需要做的事情? 我需要使promises模塊化,為它們提供盡可能多的數據。

您可以.map()覆蓋它們,如下所示:

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

由於你在服務器端,我強烈推薦Bluebird作為原生Promises的替代品。 然后你可以這樣做:

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

暫無
暫無

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

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