异步编程(回调函数,promise)
一、回调函数
①概念:一般情况下,程序会时常通过API调用库里所预先备好的函数。但是有些库函数却要求应用先传给它一个函数,好在合适的时候调用,以完成目标任务。这个被传入的、后又被调用的函数就称为回调函数(callback function),也就是一个函数作为另外一个函数的参数使用。如果需要得到一个函数内部的异步操作的结果,这时候必须通过回调函数来获取。
②推导:
③数组遍历中使用的回调函数
- every() 方法测试数组的所有元素是否都通过了指定函数的测试
function isBelowThreshold(currentValue) {
return currentValue < 40;
}
var array1 = [1, 30, 39, 29, 10, 13];
console.log(array1.every(isBelowThreshold));// true
- forEach() 方法对数组的每个元素执行一次提供的函数
var array1 = ['a', 'b', 'c'];
array1.forEach(function(element) {
console.log(element);
});
// expected output: "a"
// expected output: "b"
// expected output: "c"
- some() 方法测试数组中的某些元素是否通过由提供的函数实现的测试
var array = [1, 2, 3, 4, 5];
var even = function(element) {
// checks whether an element is even
return element % 2 === 0;
};
console.log(array.some(even));
// expected output: true
- includes() 方法用来判断一个数组是否包含一个指定的值,根据情况,如果包含则返回 true,否则返回false
var array1 = [1, 2, 3];
console.log(array1.includes(2));
// expected output: true
- map() 方法创建一个新数组,其结果是该数组中的每个元素都调用一个提供的函数后返回的结果
var array1 = [1, 4, 9, 16];
// pass a function to map
const map1 = array1.map(x => x * 2);
console.log(map1);
// expected output: Array [2, 8, 18, 32]
- reduce() 方法对累加器和数组中的每个元素(从左到右)应用一个函数,将其减少为单个值。
const array1 = [1, 2, 3, 4];
const reducer = (accumulator, currentValue) => accumulator + currentValue;
console.log(array1.reduce(reducer));
// 1 + 2 + 3 + 4
// expected output: 10 console.log(array1.reduce(reducer, 5));
// 5 + 1 + 2 + 3 + 4
// expected output: 15
④ajax请求里使用回调函数
function get(url,callback){
var oReq=new XMLHttpRequest()
// 当请求加载成功以后要调用指定的函数
oReq.onload=function(){
// 现在需要得到这里的oReq.oReq.responseText
callback(oReq.responseText)
}
oReq.open('get',url,true)
oReq.send()
}
get('data.json',function(data){
console.log(data)
})
⑤ES6的find和findindex方法
// find() 方法返回数组中满足提供的测试函数的第一个元素的值。否则返回 undefined。
var array1 = [5, 12, 8, 130, 44];
var found = array1.find(function(element) {
return element > 10;
});
console.log(found);
// expected output: 12
// findIndex()方法返回数组中满足提供的测试函数的第一个元素的索引。否则返回-1。
var array1 = [5, 12, 8, 130, 44];
function findFirstLargeNumber(element) {
return element > 13;
}
console.log(array1.findIndex(findFirstLargeNumber));
// expected output: 3
// 原理
var users=[
{id:1,name:'曹操'},
{id:2,name:'许褚'},
{id:3,name:'典韦'},
{id:4,name:'于禁'},
]
Array.prototype.myFind=function(conditionFunc){
for(var i=0;i<this.length;i++){
if(conditionFunc(this[i],i)){
return this[i]
}
}
}
var ret=users.myFind(function(item,index){
return item.id===4
});
console.log(ret);//{ id: 4, name: '于禁' }
二、promise
①无法保证顺序的代码
var fs=require('fs');
// 读取a.txt(里面包括文本 aaa)文件
fs.readFile('./a.txt','utf8',function(err,data){
if(err){
// 抛出异常:阻止程序的执行,把错误信息打印到控制台
throw err
}
console.log(data)
})
// 读取b.txt(里面包括文本 bbb)文件b
fs.readFile('./b.txt','utf8',function(err,data){
if(err){
// 抛出异常:阻止程序的执行,把错误信息打印到控制台
throw err
}
console.log(data)
})
// 读取c.txt(里面包括文本 ccc)文件
fs.readFile('./c.txt','utf8',function(err,data){
if(err){
// 抛出异常:阻止程序的执行,把错误信息打印到控制台
throw err
}
console.log(data)
})
②通过回调嵌套的方式来保证顺序
var fs=require('fs');
// 读取a.txt(里面包括文本 aaa)文件
fs.readFile('./a.txt','utf8',function(err,data){
if(err){
// 抛出异常:阻止程序的执行,把错误信息打印到控制台
throw err
}
console.log(data);
// 读取b.txt(里面包括文本 bbb)文件b
fs.readFile('./b.txt','utf8',function(err,data){
if(err){
// 抛出异常:阻止程序的执行,把错误信息打印到控制台
throw err
}
console.log(data);
// 读取c.txt(里面包括文本 ccc)文件
fs.readFile('./c.txt','utf8',function(err,data){
if(err){
// 抛出异常:阻止程序的执行,把错误信息打印到控制台
throw err
}
console.log(data)
});
});
});
③为了解决回调嵌套编码方式带来的问题(代码不美观,并且不好维护),ecmascript 6里增加了一个API:promise
- promise代码执行顺序
var fs=require('fs');
console.log(1)
// 创建promise容器:一旦建立,就开始执行里面的代码
new Promise(function(){
console.log(2);
fs.readFile('./a.txt','utf8',function(err,data){
if(err){
throw err;
}
console.log(3);
console.log(data)
});
});
console.log(4)
//执行顺序是:1 2 4 3 aaa
- promise图示
- promise基本语法
var fs=require('fs');
// 创建promise容器:一旦建立,就开始执行里面的代码
var p1=new Promise(function(resolve,reject){
fs.readFile('./aa.txt','utf8',function(err,data){
if(err){
// promise容器中的任务失败,pending状态变为rejectd
reject(err)
}else{
// promise容器中的任务成功,pending状态变为resolved
// 这里调用的resolve方法就是下面then方法传递的第一个参数function(data){}
resolve(data)
}
});
});
// 当p1成功以后,执行then方法的function(data){}
// 当p1失败以后,执行then方法的function(err){}
p1.then(function(data){
console.log(data)
},function(err){
console.log('文件读取失败',err)
})
- 解决读取多个文件的嵌套问题
var fs=require('fs');
// 读取a.txt(里面包括文本 aaa)文件
var p1=new Promise(function(resolve,reject){
fs.readFile('./a.txt','utf8',function(err,data){
if(err){
reject(err)
}else{
resolve(data)
}
});
});
// 读取b.txt(里面包括文本 bbb)文件
var p2=new Promise(function(resolve,reject){
fs.readFile('./b.txt','utf8',function(err,data){
if(err){
reject(err)
}else{
resolve(data)
}
});
});
// 读取c.txt(里面包括文本 ccc)文件
var p3=new Promise(function(resolve,reject){
fs.readFile('./c.txt','utf8',function(err,data){
if(err){
reject(err)
}else{
resolve(data)
}
});
});
// then处理:当return一个promise对象,后续的then方法中的第一个参数就会接收这个对象
p1.then(function(data){
console.log(data);
return p2//后续的then里面的第一个参数会作为p2的resolve
},function(err){
console.log('文件读取失败',err)
}).then(function(data){
console.log(data);
return p3//后续的then里面的第一个参数会作为p3的resolve
},function(err){
console.log('文件读取失败',err)
}).then(function(data){
console.log(data);
console.log('end')
},function(err){
console.log('文件读取失败',err)
})
封装promise版本的readFile方法
var fs=require('fs');
// 读取文件封装函数
function pReadFile(filePath){
return new Promise(function(resolve,reject){
fs.readFile(filePath,'utf8',function(err,data){
if(err){
reject(err)
}else{
resolve(data)
}
});
})
} pReadFile('./a.txt').then(function(data){
console.log(data);
return pReadFile('./b.txt')
}).then(function(data){
console.log(data);
return pReadFile('./c.txt')
}).then(function(data){
console.log(data);
})
⑤promise使用场景:数据来源于多个数据接口,形成的嵌套问题
⑥mongoose所有的API都支持promise
⑧参考文章:http://es6.ruanyifeng.com/#docs/promise
异步编程(回调函数,promise)的更多相关文章
- 转: ES6异步编程: co函数库的含义与用法
转: ES6异步编程: co函数库的含义与用法 co 函数库是著名程序员 TJ Holowaychuk 于2013年6月发布的一个小工具,用于 Generator 函数的自动执行. 比如,有一个 Ge ...
- 转: ES6异步编程:Thunk函数的含义与用法
转: ES6异步编程:Thunk函数的含义与用法 参数的求值策略 Thunk函数早在上个世纪60年代就诞生了. 那时,编程语言刚刚起步,计算机学家还在研究,编译器怎么写比较好.一个争论的焦点是&quo ...
- 转: ES6异步编程:Generator 函数的含义与用法
转: ES6异步编程:Generator 函数的含义与用法 异步编程对 JavaScript 语言太重要.JavaScript 只有一根线程,如果没有异步编程,根本没法用,非卡死不可. 以前,异步编程 ...
- 6.26学习 异步委托回调函数 VS 多线程 VS 并行处理
描述: 我现在是轮询着构建实例,然后这个实例去执行一个方法,但是执行方法需要大约10s时间,全部轮询下来需要很长时间.所以我现在要更改,头给了我两个方法,1多线程 2异步委托回调函数. 异步委托回调函 ...
- node.js异步编程解决方案之Promise用法
node.js异步编程解决方案之Promise var dbBase = require('../db/db_base'); var school_info_db = require('../db/s ...
- python 并发编程 同步调用和异步调用 回调函数
提交任务的两张方式: 1.同步调用 2.异步调用 同步调用:提交完任务后,就在原地等待任务执行完后,拿到结果,再执行下一行代码 同步调用,导致程序串行执行 from concurrent.future ...
- 一个例子读懂 JS 异步编程: Callback / Promise / Generator / Async
JS异步编程实践理解 回顾JS异步编程方法的发展,主要有以下几种方式: Callback Promise Generator Async 需求 显示购物车商品列表的页面,用户可以勾选想要删除商品(单选 ...
- JavaScript异步编程助手:Promise模式
:Promises是一种令代码异步行为更加优雅的抽象,它很有可能是JavaScript的下一个编程范式,一个Promise即表示任务结果,无论该任务是否完成. 异步模式在Web编程中变得越来越重要,对 ...
- Netty 中的异步编程 Future 和 Promise
Netty 中大量 I/O 操作都是异步执行,本篇博文来聊聊 Netty 中的异步编程. Java Future 提供的异步模型 JDK 5 引入了 Future 模式.Future 接口是 Java ...
随机推荐
- Expected linebreaks to be 'LF' but found 'CRLF'.
解决方法 在rules中加入 "linebreak-style": [0 ,"error", "windows"], 如果你需要知道原理,请 ...
- .NET 使用 JustAssembly 比较两个不同版本程序集的 API 变化
原文:.NET 使用 JustAssembly 比较两个不同版本程序集的 API 变化 最近我大幅度重构了我一个库的项目结构,使之使用最新的项目文件格式(基于 Microsoft.NET.Sdk)并使 ...
- WPF 的命令的自动刷新时机——当你 CanExecute 会返回 true 但命令依旧不可用时可能是这些原因
原文:WPF 的命令的自动刷新时机--当你 CanExecute 会返回 true 但命令依旧不可用时可能是这些原因 在 WPF 中,你可以使用 Command="{Binding Walt ...
- 转:更改pip源至国内镜像,显著提升下载速度
经常在使用python的时候需要安装各种模块,而pip是很强大的模块安装工具,但是由于国外官方pypi经常被墙,导致不可用,所以我们最好是将自己使用的pip源更换一下,这样就能解决被墙导致的装不上库的 ...
- php长连接应用
php长连接和短连接 2012-12-05 17:25 3529人阅读 评论(0) 收藏 举报 分类: 我的收藏(8) 什么是长连接,如果你没听说过,可以往下看! 长连接到底有什么用?我想你应该见 ...
- Android为TV端助力之点击Textview无效
记录一下如果有两个Textview都有点击事件,那么不能给Textview同时设置 android:focusable="true"android:focusableInTouch ...
- c语言学习目标
运行c语言环境codeblocks. codeblocks的安装: 安装地址:http://www.codeblocks.org/downloads/26 codeblocks-16.01mingw- ...
- mysql DML select查询
windows上的操作 1.从官网下载mysql 下载navicat,用来连接mysql的 2.打开运行启动mysql 3.在navicat上的连接打开新建连接 然后输入链接名,连接名就是用户名,自己 ...
- Apache 正向代理与反向代理配置
Apache提供了 mod_proxy 模块用于提供代理服务,能够支持的包括正向代理.反向代理.透明代理.缓存.负载均衡,HTTP代理.FTP代理.SSL代理等若干强大的功能. 配置代理方法很简单那, ...
- Vi 和 Vim 编辑器详细使用方法
学习linux的一项必会技能,熟练使用vi/vim编辑器那便最重要的了.不过一堆操作看的也是太头疼了,以下整理了些常用到的命令. 工作模式 vi编辑界面有三种不同的工作模式,分别为命令模式.输入模式. ...