在JavaScript的世界中,所有代码都是单线程执行的。
JavaScript的所有网络操作,浏览器事件,都必须是异步执行:
function callback() {
console.log('Done');
}
console.log('before setTimeout()');
setTimeout(callback, 1000); // 1秒钟后调用callback函数
console.log('after setTimeout()');
AJAX就是典型的异步操作
request.onreadystatechange = function () {
if (request.readyState === 4) {
if (request.status === 200) {
return success(request.responseText);
} else {
return fail(request.status);
}
}
}
更好的写法
var ajax = ajaxGet('http://...');
ajax.ifSuccess(success)
.ifFail(fail);
先统一执行AJAX逻辑,不关心如何处理结果,然后,根据结果是成功还是失败,在将来的某个时候调用success函数或fail函数。
“承诺将来会执行”的对象在JavaScript中称为Promise对象。(ES6)
例子
执行函数
function test(resolve, reject) {
var timeOut = Math.random() * 2;
log('set timeout to: ' + timeOut + ' seconds.');
setTimeout(function () {
if (timeOut < 1) {
log('call resolve()...');
resolve('200 OK');
}
else {
log('call reject()...');
reject('timeout in ' + timeOut + ' seconds.');
}
}, timeOut * 1000);
}
var p1 = new Promise(test);
var p2 = p1.then(function (result) {
console.log('成功:' + result);
});
var p3 = p2.catch(function (reason) {
console.log('失败:' + reason);
});
// 如果成功,执行这个函数:
p1.then(function (result) {
console.log('成功:' + result);
});
p2.catch(function (reason) {
console.log('失败:' + reason);
});
简化为
new Promise(test).then(function (result) {
console.log('成功:' + result);
}).catch(function (reason) {
console.log('失败:' + reason);
});
完整代码
<div id="test-promise-log" style="border: solid 1px #ccc; padding: 1em; margin: 15px 0;">
<p>Log:</p>
</div>
'use strict';
// 清除log:
var logging = document.getElementById('test-promise-log');
while (logging.children.length > 1) {
logging.removeChild(logging.children[logging.children.length - 1]);
}
// 输出log到页面:
function log(s) {
var p = document.createElement('p');
p.innerHTML = s;
logging.appendChild(p);
}
new Promise(function (resolve, reject) {
log('start new Promise...');
var timeOut = Math.random() * 2;
log('set timeout to: ' + timeOut + ' seconds.');
setTimeout(function () {
if (timeOut < 1) {
log('call resolve()...');
resolve('200 OK');
}
else {
log('call reject()...');
reject('timeout in ' + timeOut + ' seconds.');
}
}, timeOut * 1000);
}).then(function (r) {
log('Done: ' + r);
}).catch(function (reason) {
log('Failed: ' + reason);
});