admin管理员组文章数量:1316023
I'm not quite sure, and maybe I'm missing something obvious, but I cannot figure out how to chain two promises.
My callback-based code looks something like this:
async.series([
function (cb) {
// Create the directory if the nodir switch isn't on
if (!nodir) {
fs.mkdir('somedirectory', function (err) {
if (err) {
log('error while trying to create the directory:\n\t %s', err)
process.exit(0)
}
log('successfully created directory at %s/somedirectory', process.cwd())
cb(null)
})
}
cb(null)
},
function (cb) {
// Get the contents of the sample YML
fs.readFile(path.dirname(__dirname) + '/util/sample_config.yml', function (err, c) {
var sampleContent = c
if (err) {
log('error while reading the sample file:\n\t %s', err)
process.exit(0)
}
log('pulled sample content...')
// Write the config file
fs.writeFile('db/config.yml', sampleContent, function (err) {
if (err) {
log('error writing config file:\n\t %s', err)
process.exit(0)
}
log('successfully wrote file to %s/db/config.yml', process.cwd())
cb(null)
})
})
}
])
I've begun to try and refactor this to promise-based flow, this is what I have so far:
if (!nodir) {
fs.mkdirAsync('somedirectory').then(function () {
log('successfully created directory at %s/somedirectory', process.cwd())
}).then(function () {
// how can I put fs.readFileAsync here? where does it fit?
}).catch(function (err) {
log('error while trying to create the directory:\n\t %s', err)
process.exit(0)
})
}
(I'm using Bluebird, so I did Promise.promisifyAll(fs)
before)
The problem is, I have no idea where to put the second "step" of the previous series. Do I put it in then
or in its function? Do I return it and put it in a separate function?
Any help would greatly be appreciated.
I'm not quite sure, and maybe I'm missing something obvious, but I cannot figure out how to chain two promises.
My callback-based code looks something like this:
async.series([
function (cb) {
// Create the directory if the nodir switch isn't on
if (!nodir) {
fs.mkdir('somedirectory', function (err) {
if (err) {
log('error while trying to create the directory:\n\t %s', err)
process.exit(0)
}
log('successfully created directory at %s/somedirectory', process.cwd())
cb(null)
})
}
cb(null)
},
function (cb) {
// Get the contents of the sample YML
fs.readFile(path.dirname(__dirname) + '/util/sample_config.yml', function (err, c) {
var sampleContent = c
if (err) {
log('error while reading the sample file:\n\t %s', err)
process.exit(0)
}
log('pulled sample content...')
// Write the config file
fs.writeFile('db/config.yml', sampleContent, function (err) {
if (err) {
log('error writing config file:\n\t %s', err)
process.exit(0)
}
log('successfully wrote file to %s/db/config.yml', process.cwd())
cb(null)
})
})
}
])
I've begun to try and refactor this to promise-based flow, this is what I have so far:
if (!nodir) {
fs.mkdirAsync('somedirectory').then(function () {
log('successfully created directory at %s/somedirectory', process.cwd())
}).then(function () {
// how can I put fs.readFileAsync here? where does it fit?
}).catch(function (err) {
log('error while trying to create the directory:\n\t %s', err)
process.exit(0)
})
}
(I'm using Bluebird, so I did Promise.promisifyAll(fs)
before)
The problem is, I have no idea where to put the second "step" of the previous series. Do I put it in then
or in its function? Do I return it and put it in a separate function?
Any help would greatly be appreciated.
Share Improve this question asked May 22, 2015 at 19:55 jonajona 3994 silver badges14 bronze badges2 Answers
Reset to default 5Normally promise-driven code looks like this:
operation.then(function(result) {
return nextOperation();
}).then(function(nextResult) {
return finalOperation();
}).then(function(finalResult) {
})
There's a lot going on in your example, but the general idea would be something like:
Promise.resolve().then(function() {
if (nodir) {
return fs.mkdir('somedirectory').catch(function(err) {
log('error while trying to create the directory:\n\t %s', err);
process.exit(0);
});
}
}).then(function() {
return fs.readFile(path.dirname(__dirname) + '/util/sample_config.yml').catch(function(err) {
log('error while reading the sample file:\n\t %s', err);
process.exit(0);
})
}).then(function(sampleContent) {
log('pulled sample content...');
return fs.writeFile('db/config.yml', sampleContent).catch(function(err) {
log('error writing config file:\n\t %s', err)
process.exit(0)
})
}).then(function() {
log('successfully wrote file to %s/db/config.yml', process.cwd())
})
This presumes all the calls you're using are promise native.
The original Promise.resolve()
is simply something to start out the chain with a promise since your first step is conditional.
Since you're using Bluebird, you can use a lot of sugar and have much much cleaner code than the accepted answer IMO:
var fs = Promise.promisifyAll(fs); // tell bluebird to work with FS
Promise.try(function(){
if(nodir) return fs.mkdirAsync('somedirectory').
catch(catchErr("Could not create dir"));
}).then(function(){
return fs.readFileAsync(path.dirname(__dirname) + '/util/sample_config.yml').
catch(catchErr("error while reading the sample file"));
}).then(function(data){
log('pulled sample content...');
return fs.writeFile('db/config.yml', data).
catch(catchErr("error writing config file"));
}).then(function(){
log('successfully wrote file to %s/db/config.yml', process.cwd())
}, function(err){
// centralized error handling, to remove the redundancy
log(err.message);
log(err.internal);
log(err.stack); // this is important!
});
function catchErr(msg){ // helper to rethrow with a specific message
return function(e){
var err = new Error(msg);
err.internal = e; // wrap the error;
throw e;
};
}
I'd go further though, and would remove the finer grained errors you have here since the types you use really provide no additional info over the built in messages these API methods provide - shortening your code to:
Promise.try(function(){
if(nodir) return fs.mkdirAsync("somedirectory");
}).then(function(){
fs.readFileAync(path.dirname(__dirname) + '/util/sample_config.yml');
}).then(function(data){
log('pulled sample content...');
return fs.writeFile('db/config.yml', data);
}).then(function(){
log('successfully wrote file to %s/db/config.yml', process.cwd())
}).catch(function(err){
log(err);
process.exit(1);
});
Promises are throw safe and provide sane and certralized error handling - pretty nice win if you ask me. It gets better though, if you're on io.js or modern node you can use:
Promise.coroutine(function*(){ // generators ftw
if(nodir) yield fs.mkdirAsync("somedirectory");
var data = yield fs.readFileAsync(path.dirname(__dirname) + '/util/sample_config.yml');
log("pulled sample content");
yield fs.writeFileAsync("db/config.yml", data);
log('successfully wrote file to %s/db/config.yml', process.cwd());
})();
process.on("unhandledRejection", function(p, r){
throw r; // quit process on promise failing
});
本文标签: javascriptHow do I chain multiple promisesStack Overflow
版权声明:本文标题:javascript - How do I chain multiple promises? - Stack Overflow 内容由网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://www.betaflare.com/web/1741992782a2409443.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
发表评论