Open ntscshen opened 7 years ago
function ajax(json) {
json = json || {}; // 如果没有数据传入则 - 赋值{}
if (!json.url) { // 如果没传递url - 则返回
return;
}
json.data = json.data || {};
json.type = json.type || 'get'; // 默认提交方式GET
// 获取ajax
var XHR = new XMLHttpRequest();
// 判断传递的类型
switch (json.type.toLowerCase()) {
case 'get':
XHR.open('GET', json.url + '?' + getData(json.data), true);
// 发送数据
XHR.send();
break;
case 'post':
XHR.open('POST', json.url, true);
XHR.setRequestHeader('content-type', 'application/x-www-form-urlencoded'); // 设置请求头信息
XHR.send(getData(json.data));
break;
}
// 接收数据 - 状态监控
XHR.onreadystatechange = function() {
if (XHR.readyState === 4) {
if (XHR.status >= 200 && XHR.status < 300 || XHR.status == 304) {
// 执行成功的回调函数
json.success && json.success(JSON.parse(XHR.responseText));
} else {
json.error && json.error(XHR.status);
}
}
}
}
// 对传入的参数做处理
function getData(json) {
var arr = [];
for (var name in json) {
arr.push((encodeURIComponent(name) + '=' + encodeURIComponent(json[name])));
// encodeURIComponent // 为了处理中文
}
return arr.join('&');
}
function ajax(options) {
return new Promise((resolve, reject) => {
let {
url = new Error('url must a string'),
method = 'get',
dataType = 'text',
data = null,
success,
error
} = options;
// 获取ajax
var XHR = new XMLHttpRequest();
// 判断传递的类型
switch (options.type.toLowerCase()) {
case 'get':
XHR.open('GET', `${url}?${getData(options.data)}`, true);
XHR.send();
break;
case 'post':
XHR.open('POST', options.url, true);
XHR.setRequestHeader('content-type', 'application/x-www-form-urlencoded'); // 设置请求头信息
XHR.send(getData(options.data));
break;
}
XHR.responseType = dataType;
// 接收数据 - 状态监控
XHR.onreadystatechange = function() {
if (XHR.readyState === 4) {
if (XHR.status >= 200 && XHR.status < 300 || XHR.status == 304) {
// 执行成功的回调函数
options.success && options.success(options.parse(XHR.responseText));
resolve(options.parse(XHR.responseText));
} else {
options.error && options.error(XHR.status);
reject(XHR.status);
}
}
}
// 错误
XHR.onerror = function(err) {
error && error(err);
reject(err);
}
});
}
// 对传入的参数做处理
function getData(options) {
var arr = [];
for (var name in options) {
arr.push((encodeURIComponent(name) + '=' + encodeURIComponent(options[name])));
// encodeURIComponent // 为了处理中文
}
return arr.join('&');
}
// 使用
ajax({
url: '/login',
method: 'post',
dataType: 'json',
data: {'name': 'ntscshen','age': '25'},
}).then(data => {
console.log(data);
}).catch(e => {
console.log(e);
});
// JSONP
function jsonp(options) {
options = options || {};
if (!options.url || !options.callback) {
throw new Error("参数不合法");
}
// 创建script标签并加入页面中
var callbackName = ('jsonp_' + Math.random()).replace(".", "");
var oHead = document.getElementsByTagName('head')[0];
var oScript = document.createElement('script');
oHead.appendChild(oScript);
options.data[options.callback] = callbackName;
var params = formatParams(options.data); // 格式化数据
// 创建jsonp回调函数
// callbackName是一个变量 - 而且必须是全局变量 - 因此window[callbackName]怎么去使用
// script标签的src属性只在第一次设置的时候起作用,导致script标签没法重用。每次完成操作之后都需要移除。
window[callbackName] = function(json) {
options.success && options.success(json);
oHead.removeChild(oScript);
try {
delete window[callbackName];
} catch (e) {}
window[callbackName] = null;
}
// 发送请求
oScript.src = options.url + (options.url.indexOf("?") > -1 ? "" : "?") + params;
}
// 数据参数格式化
function formatParams(data) {
var arr = [];
var str = '';
for (var key in data) {
if (data.hasOwnProperty(key)) {
// arr.push(encodeURIComponent(name) + '=' + encodeURIComponent(data[i]));
str += encodeURIComponent(key) + '=' + encodeURIComponent(data[key]) + "&";
}
}
return str;
// return arr.join('&');
}
// url中的data数据格式化 - 优化
function formatParams(data) {
let str = ''
for (let key in data) {
if (data.hasOwnProperty(key)) { // 遍历对象所有属性,忽略掉继承属性
// 判断传递的参数中是否有undefined如果有则置空,否则原有数据不变
let value = data[key] === undefined ? '' : data[key]
str += `&${encodeURIComponent(key)}=${encodeURIComponent(value)}`
}
}
// 删除第一个&
return str ? str.substring(1) : ''
}
// 调用
formatParams({
'name': 'ntscshen',
'format': 'jsonp',
'jsonpCallback': 'jsonp1'
})
function xxx(rul, data){
url += (url.indexOf('?') < 0 ? '?' : '&') + formatParams(data)
}
// new一个Promise对象,并没有调用它,我们传递进去的函数就已经被执行了。这是一个很重要的细节点,所以我们用Promise的时候一般是包在一个函数中,在需要的时候去运行这个函数
// Promise :优势在于,可以在then方法中继续写Promise对象并返回,让后继续调用thne来进行回调操作
// Promise不仅仅是简化了 层层回调的写法
// 实质上,Promise的精髓在于"状态",用户维护状态、传递状态的方式来使得回调函数能够及时被调用。比callback简单、灵活
function runAsync(){
return new Promise((resolve, reject) => {
// 做异步操作
setTimeout(() => {
console.log('异步任务、执行完成');
resolve('数据')
}, 1000)
})
}
function runAsync1(){
return new Promise((resolve, reject) => {
setTimeout(function(){
console.log('异步任务1、执行完成');
resolve('数据1')
}, 1000)
})
}
function runAsync2(){
return new Promise((resolve, reject) => {
setTimeout(function(){
console.log('异步任务2、执行完成');
resolve('数据2')
}, 1000)
})
}
// 调用
runAsync().then((data) => {
console.log(data);
return runAsync1();
}).then((data) => {
console.log(data);
})
建议看一下ES6 的Generator函数以及async await,Promise还不是异步的最终答案
// Generator生成器 => 迭代器
function* gen() {
let a = yield new Promise();
let b = yield new Promise();
return b;
}
gen().next().value.then(data => {
// let a 中的promise
// next传递給let b
gen().next(data).value.then(data => {
console.log(gen().next(data).value.toString());
});
});
// co原理
// 1、co链式调用(Promise)
// 2、异步迭代
function co(gen) {
return new Promise((resolve, reject) => {
function step() {
let { value, done } = gen.next(data); // {value: 'XXX', done: false}
if (!done) {
value.then(data => {
step(data); // 成功后迭代
}, reject);// reject有一次失败即失败
} else { // 成功
resolve(value);
}
}
step();
});
}
Generator + co
的语法糖async
函数的返回结果是promise
,await
后面必须跟着promise
await
只能出现在async
函数中async await
中是同步阻塞的异步执行 其并不能代替promise
。 如果多个请求并发请使用Promise.all([xx,xx,xx]);
// babel在编译时,会把async转换成了generator。 这也许是答案
function _asyncToGenerator(fn) {
return function () {
var gen = fn.apply(this, arguments);
return new Promise(function (resolve, reject) {
function step(key, arg) {
try {
var info = gen[key](arg);
var value = info.value;
} catch (error) {
reject(error); return;
}
if (info.done) {
resolve(value);
} else {
return Promise.resolve(value).then(function (value) {
step("next", value);
}, function (err) {
step("throw", err);
});
}
}
return step("next");
});
};
}
什么是Ajax?为什么要使用Ajax?