[英]Modular promises and Promise.all()
I have a bunch of functions that return promises that I want to make generalized, and so I write them like this: 我有一堆函数返回我希望进行泛化的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;
}
I resolve data in each function because I plan to have a lot of these types of functions, and I don't know the order they'll be called in while chaining: 我解析每个函数中的数据,因为我计划有很多这些类型的函数,我不知道链接时它们将被调用的顺序:
readfile(somedata)
.then(upload)
.then(delete)
.then(save)
//etc
This works fine until I have to do Promise.all: 这工作正常,直到我必须做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
Using Promise.all().then(upload)
gives me errors, because the new promise returned by Promise.all() is an object that contains both resolutions from checkWebpageForReference
and takeScreenshot
. 使用
Promise.all().then(upload)
给我错误,因为Promise.all()返回的新承诺是一个包含来自checkWebpageForReference
和takeScreenshot
分辨率的对象。 Essentially, in readFile
, I can't access data
fields because the resulting promise is [data, data]
. 本质上,在
readFile
,我无法访问data
字段,因为生成的promise是[data, data]
。
Is there a pattern I can follow to help me achieve what I need to do? 是否有一种模式可以帮助我实现我需要做的事情? I need to make the promises modular providing them with as much data as possible.
我需要使promises模块化,为它们提供尽可能多的数据。
You can .map()
over them like so: 您可以
.map()
覆盖它们,如下所示:
Promise.all(...)
.then(datas => Promise.all(datas.map(upload)));
Since you're on the server side, I highly recommend Bluebird as a drop-in replacement for native Promises. 由于你在服务器端,我强烈推荐Bluebird作为原生Promises的替代品。 Then you can do:
然后你可以这样做:
Promise.all(...)
.map(upload);
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.