回调函数是一个经过指针调用的函数。若是你把这个指针做为参数传给另外一个函数,当这个指针指向的函数被调用的时候,咱们就说和这个函数是回调函数。回调函数不是由函数的实现方直接调用的,而是在特定的时间或者条件,由另外一方函数调用。java
把调用者和被调用者区分开,调用者不关心谁是被调用者,它只需知道存在一个具备特定原型的和限制条件的被调用者函数。简而言之,回调函数容许用户把须要调用的函数做为一个指针传给另外一个函数,使程序更加灵活。编程
fs.readdir(source, function (err, files) {
if (err) {
console.log('Error finding files: ' + err)
} else {
files.forEach(function (filename, fileIndex) {
console.log(filename)
gm(source + filename).size(function (err, values) {
if (err) {
console.log('Error identifying file size: ' + err)
} else {
console.log(filename + ' : ' + values)
aspect = (values.width / values.height)
widths.forEach(function (width, widthIndex) {
height = Math.round(width / aspect)
console.log('resizing ' + filename + 'to ' + height + 'x' + height)
this.resize(width, height).write(dest + 'w' + width + '_' + filename, function(err) {
if (err) console.log('Error writing file: ' + err)
})
}.bind(this))
}
})
})
}
})
复制代码
回调地狱的缘由是当编写人员以重上往下视觉方式编写JavaScript。不少人都会犯这个错误!在C,java,Ruby,Python等语言中,编写人员指望第一行发生的任何事情都会在第二行代码运行开始以前被完成,依次类推。就会产生上述结果。promise
三个原则:bash
源代码
var form = document.querySelector('form')
form.onsubmit = function (submitEvent) {
var name = document.querySelector('input').value
request({
uri: "http://example.com/upload",
body: name,
method: "POST"
}, function (err, response, body) {
var statusMessage = document.querySelector('.status')
if (err) return statusMessage.value = err
statusMessage.value = body
})
}
复制代码
代码分解
document.querySelector('form').onsubmit = formSubmit
function formSubmit (submitEvent) {
var name = document.querySelector('input').value
request({
uri: "http://example.com/upload",
body: name,
method: "POST"
}, postResponse)
}
function postResponse (err, response, body) {
var statusMessage = document.querySelector('.status')
if (err) return statusMessage.value = err
statusMessage.value = body
}
复制代码
一方面监听事件发生,若是发生执行相应的回调,另外一方面,监听操做的完成,当操做完成时进行相应的回调。异步
readFile('./sample.txt').then(content => {
let keyword = content.substring(0, 5);
return queryDB(keyword);
}).then(res => {
return getData(res.length);
}).then(data => {
console.log(data);
}).catch(err => {
console.warn(err);
});
复制代码
// 咱们的主任务——显示关键字
// 使用yield暂时中断下方代码执行
// yield后面为promise对象
const showKeyword = function* (filepath) {
console.log('开始读取');
let keyword1 = yield readFile(filepath);
let keyword2 = yield readFile(filepath);
}
// generator的流程控制
let gen = showKeyword();
let res = gen.next();
let res1 = gen.next();
复制代码
能够看到,上面的方法虽然都在必定程度上解决了异步编程中回调带来的问题。然而:async
所以,这里再介绍一个方法,它就是es7中的async/await。ide
简单介绍一下async/await。基本上,任何一个函数均可以成为async函数,如下都是合法的书写形式:模块化
const printData = async function (filepath) {
let keyword = await readFile(filepath);
let count = await queryDB(keyword);
let data = await getData(res.length);
console.log(data);
});
printData('./sample.txt');
复制代码