Skip to content

Instantly share code, notes, and snippets.

@Jamlee
Last active April 10, 2021 21:49
Show Gist options
  • Save Jamlee/c8cb6fc60df9c0e48c49648eef593fe7 to your computer and use it in GitHub Desktop.
Save Jamlee/c8cb6fc60df9c0e48c49648eef593fe7 to your computer and use it in GitHub Desktop.
异步: promise, javascript 实现
var fs = require('fs');
var readFile = function (fileName){
return new Promise(function (resolve, reject){
fs.readFile(fileName, function(error, data){
if (error) reject(error);
resolve(data);
});
});
};
var gen = function* (){
var f1 = yield readFile('/etc/fstab');
var f2 = yield readFile('/etc/shells');
console.log(f1.toString());
console.log(f2.toString());
}
var g = gen();
function run(gen){
var g = gen();
function next(data){
var result = g.next(data);
if (result.done) return result.value;
result.value.then(function(data){
next(data);
});
}
next();
}
run(gen);
//一个简易的promise实现
fs = require('fs')
const util = require('util')
var PENDING = 0;
var FULFILLED = 1;
var REJECTED = 2;
function Promise(fn) {
// store state which can be PENDING, FULFILLED or REJECTED
var state = PENDING;
// store value once FULFILLED or REJECTED
var value = null;
// store sucess & failure handlers
var handlers = [];
this.done = function (onFulfilledHandler, onRejectedHandler) {
// 确保是异步操作
setTimeout(function () {
handle({
onFulfilled: onFulfilledHandler,
onRejected: onRejectedHandler
});
}, 0);
}
this.then = function (onFulfilled, onRejected) {
var self = this;
return new Promise(function (resolve, reject) {
self.done(function (result) {
if (typeof onFulfilled === 'function') {
try {
return resolve(onFulfilled(result));
} catch (ex) {
return reject(ex);
}
} else {
return resolve(result);
}
}, function (error) {
if (typeof onRejected === 'function') {
try {
return resolve(onRejected(error));
} catch (ex) {
return reject(ex);
}
} else {
return reject(error);
}
});
});
}
function reject(error) {
console.log('4. 异常-> 解析第一个异步操作返回的结果')
state = REJECTED;
value = error;
// 处理内部的handlers列表
handlers.forEach(handle);
handlers = null;
}
function resolve(result) {
console.log('4. 正常-> 解析第一个异步操作返回的结果')
function fulfill(result) {
state = FULFILLED;
value = result;
// 处理内部的handlers列表
handlers.forEach(handle);
handlers = null;
}
function getThen(value) {
var t = typeof value;
if (value && (t === 'object' || t === 'function')) {
var then = value.then;
if (typeof then === 'function') {
return then;
}
}
return null;
}
try {
var then = getThen(result);
if (then) {
console.log('4.1 如果返回的结果是thenable,继续调用doResolve')
doResolve(then.bind(result), resolve, reject)
return
}
console.log('4.1 如果返回的结果不是thenable, 将当前的promise对象的状态改为 `fulfill`')
fulfill(result);
} catch (e) {
reject(e);
}
}
function handle(handler) {
if (state === PENDING) {
handlers.push(handler);
} else {
if (state === FULFILLED &&
typeof handler.onFulfilled === 'function') {
console.log('5. 操作完成, 执行用户定义的done函数-正常')
handler.onFulfilled(value);
}
if (state === REJECTED &&
typeof handler.onRejected === 'function') {
onsole.log('5. 操作完成, 执行用户定义的done函数-异常')
handler.onRejected(value);
}
}
console.log(handlers)
}
/**
*
*/
function doResolve(fn, onFulfilled, onRejected) {
var done = false;
try {
//执行异步函数
fn(/* fulfill函数 */function (value) {
//本函数对promise 工厂函数内部的的resolve函数进行 `装饰`
if (done) return
console.log('3. 正常情况下, 改变promise对象的状态')
done = true
onFulfilled(value)
}, /* rejected函数 */ function (reason) {
//对promise 工厂函数内部的的reject函数 进行 `装饰`
if (done) return
console.log('3. 异常情况下,改变promise对象的状态')
done = true
onRejected(reason)
})
} catch (ex) {
if (done) return
done = true
onRejected(ex)
}
}
console.log('2. 生成一个Pormise对象')
console.log(' ' + util.inspect(this, {showHidden: false, depth: null}))
/**
* 将函数与promise工厂的resolve, reject 连接起来
*/
doResolve(fn, resolve, reject)
}
/**
* Demo
*
* 本地异步读取文件信息
*/
console.log('1. 包装异步操作为Promise')
function readFile(filename, enc) {
/**
* fulfill, reject 由Promise工厂提供
*/
return new Promise(function (fulfill, reject) {
fs.readFile(filename, enc, function (err, res) {
if (err) reject(err);
else fulfill(res);
});
});
}
filename = './test.json'
promise = readFile(filename, 'utf8');
// promise.done(function (res) {
// console.log('读取成功!!!')
// return '步骤二'
// }, function () {
// console.log('读取出错!!!')
// });
promise.then(function (res) {
console.log('链式调用第一环')
}, function (err) {
console.log('链式调用第一环错误')
}).then(function (res) {
console.log('链式调用第二环')
}, function (err) {
console.log('链式调用第二环错误')
});
/**
* 结论:
*
* 1. Promise 是一个 `工厂方法`, 所以Promise对象通过闭包保留了对函数内部定义的函数对象、普通对象的引用。换句话说,每个Promise对象的有自己的state、handler、value。
*
* 2. 当new Promise(function (resolve, reject){}) 时, 实际上参数中的异步操作已经执行并且获得结果, done方法仅仅处理调用后的结果。那么这里存在一个问题如何保证在调用done时,异步操作已经操作完成? 调用done时,如果当前的状态是 pending 就加入到handler中。如果 promise 初始化是在调用done之前完成,promise的state已经通过new Promise(function (resolve, reject){})中的fulfill函数变为fulfill,调用done时直接获得结果。 如果 promise 初始化是在调用done之后完成,done会处于在handlers中,等待new Promise(function (resolve, reject){})中的fulfill被执行。
*
* 3. promise对象的接口: resolve, reject, doResolve, handle, then, done
*/
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment