导航
异步编程的一种解决方案
var promise = new Promise(function(resolve, reject) {
setTimeout(function() {
Math.random() * 100 > 60 ? resolve('ok') : reject('no')
})
})
promise.then(val => {
console.log(val);
}, reason => {
console.log(reason);
})
var promise = new Promise(function(resolve, reject){
setTimeout(function(){
Math.random() * 100 > 60 ? resolve('ok') : reject('no')
})
})
promise.then(val => {
console.log(val);
return 1
}, reason => {
console.log(reason);
return 2
}).then(val => {
console.log('then2-', val);
}, reason => {
console.log('then2-', reason);
})
var promise = new Promise(function(resolve, reject) {
setInterval(function() {
Math.random() * 100 > 60 ? resolve('ok') : reject('no')
})
})
promise.then(val => {
console.log(val);
return new Promise((resolve, reject) => {
resolve('new promise')
})
}, reason => {
console.log(reason);
return 2
}).then(val => {
console.log('then2-', val);
}, reason => {
console.log('then2-', reason);
})
var promise = new Promise((resolve, reject) => {
resolve(a);
})
promise.then((val) => {
console.log('resolve', val);
}, (reason) => {
console.log('reject', reason);
})
var promise = new Promise((resolve, reject) => {
resolve(a);
})
promise.then(null, (reason) => {
console.log('reject', reason);
})
promise.catch((reason) => {
console.log('reject', reason);
})
var promise = new Promise((resolve, reject) => {
resolve('ok');
console.log(a); // 这个报错因为状态固化,无法被捕获
})
promise.then((val) => {
console.log('res', val);
}).catch((reason) => {
console.log('reject', reason);
})
var promise = new Promise((resolve, reject) => {
resolve(1);
});
promise
.then((val) => {
console.log("res", val);
throw new Error("then error");
})
.then()
.then()
.catch((reason) => {
console.log("reject", reason);
});
值穿透指的是,链式调用的参数不是函数时,会发生值穿透,就传入的非函数值忽略,传入的是之前的函数参数。
Promise.resolve(1)
.then(2)
.then(Promise.resolve(3))
.then(console.log)
// 答案:
// 传入2或者promise的fulfilled状态都会发生值穿透。
// 打印 1
Promise.resolve(1)
.then(2)
.then(Promise.reject(3))
.then(
console.log
, console.log
);
// 答案:
// 打印 1 然后报错
Promise {<fulfilled>: undefined}
VM384:3 Uncaught (in promise) 3
Promise.resolve(1)
.then(() => { return 2 })
.then(() => { return 3 })
.then(console.log)
// 答案
// 3
Promise.resolve(1)
.then(function () {
return 2
})
.then(() => { Promise.resolve(3) })
.then(console.log)
// 答案
// undefined
let promise = new Promise((resolve, reject) => {
resolve('First resolve');
});
promise.then(value => {
return value;
})
.then((value) => {
return new Promise((resolve, reject) => {
setTimeout(() => {
reject('ERROR');
}, 2000);
});
})
.then(value => {
console.log(value);
}, reason => {
console.log('Rejected: ' + reason); // Rejected: ERROR
})
.then(value => {
throw new Error('Throw Error');
})
.then(value => {
console.log(value);
}, reason => {
console.log('Then: ' + reason); // Then: Error: Throw Error
})
.catch(err => {
console.log('Catch: ' + err);
});
Promise.reject(1)
.then(res => {
console.log(res);
})
.then(res => { console.log(res) },
rej => {
console.log(`rej****${rej}`);
})
.catch(err => {
console.log(`err****${err}`);
})
// 答案:
// rej****1
Promise.reject(1)
.then(res => {
console.log(res);
})
.then(res => { console.log(res) },
rej => {
console.log(`rej****${rej}`);
})
.then(res => {
console.log(`res****${res}`);
}, rej => {
console.log(`rej****${rej}`);
})
.catch(err => {
console.log(`err${err}`);
})
// 答案:
// rej****1
// res****undefined
let promise = new Promise((resolve, reject) => {
resolve('First resolve');
});
promise.then(value => {
return value;
})
.then((value) => {
return new Promise((resolve, reject) => {
setTimeout(() => {
reject('ERROR');
}, 2000);
});
})
.then(value => {
console.log(value);
}, reason => {
console.log('Rejected: ' + reason); // Rejected: ERROR
})
.then(value => {
throw new Error('Throw Error');
})
.then(value => {
console.log(value);
})
.catch(err => {
console.log('Catch: ' + err); // Catch: Error: Throw Error
return 'Catch Error';
})
.then(value => {
console.log('Then: ' + value); // Then: Catch Error
});
var p1 = new Promise((resolve, reject) => {
setTimeout(function(){
reject(new Error('fail'));
}, 3000);
})
var p2 = new Promise((resolve, reject) => {
setTimeout(function(){
resolve(p1);
}, 1000);
})
p2.then(res => console.log('res', res))
.catch(err => console.log('p2-err-', err))
const p1 = new Promise((resolve, reject) => {
setTimeout(() => {
resolve(1);
}, 1000);
});
const p2 = new Promise((resolve, reject) => {
reject(p1);
});
p2.then(value => {
console.log('value', value);
}, err => {
console.log('err', err);
err.then(val => console.log(val), err => console.log(err));
});
var p1 = new Promise((resolve, reject) => {
resolve(1);
console.log(a) // resolve 后的错误不会被捕获
})
p1.then(res => console.log(res))
.catch(err => console.log('p1-err-', err))
console.log(3);
但如果 resolve、reject 之后的代码不报错,还是会正常执行:
var p1 = new Promise((resolve, reject) => {
resolve(1);
console.log(233)
})
p1.then(res => console.log(res))
.catch(err => console.log('p1-err-', err))
console.log(3);
var p1 = new Promise((resolve, reject) => {
reject(new Error());
console.log(2)
})
p1.then(res => console.log(res))
.catch(err => console.log('p1-err-', err))
console.log(3);
var p1 = new Promise((resolve, reject) => {
reject(new Error());
console.log(a); // reject后的错误不会被捕获
})
p1.then(res => console.log(res))
.catch(err => console.log('p1-err-', err))
console.log(3);
const fs = require('fs');
var p1 = new Promise((resolve, reject) => {
fs.readFile('./name.txt', 'utf-8', function(err, data){
if(err){
console.log(err);
}
resolve(data);
})
})
var p2 = new Promise((resolve, reject) => {
fs.readFile('./number.txt', 'utf-8', function(err, data){
if(err){
console.log(err);
}
resolve(data);
})
})
var p3 = new Promise((resolve, reject) => {
fs.readFile('./score.txt', 'utf-8', function(err, data){
if(err){
console.log(err);
}
resolve(data);
})
})
var p = Promise.all([p1, p2, p3]);
var p1 = new Promise((resolve, reject) => {
setTimeout(function(){
resolve('p1: 1000')
}, 1000)
})
var p2 = new Promise((resolve, reject) => {
setTimeout(function(){
resolve('p2: 2000')
}, 2000)
})
var p3 = new Promise((resolve, reject) => {
setTimeout(function(){
resolve('p3: 3000')
}, 3000)
})
var p = Promise.all([p1, p2, p3]);
p.then(res => console.log('res', res))
.catch(err => console.log('err', err))
var p1 = new Promise((resolve, reject) => {
setTimeout(function(){
reject('p1: 1000')
}, 1000)
})
var p2 = new Promise((resolve, reject) => {
setTimeout(function(){
reject('p2: 2000')
}, 2000)
})
var p3 = new Promise((resolve, reject) => {
setTimeout(function(){
reject('p3: 3000')
}, 3000)
})
var p = Promise.all([p1, p2, p3]);
p.then(res => console.log('res', res))
.catch(err => console.log('err', err))
var p1 = new Promise((resolve, reject) => {
setTimeout(function(){
resolve('p1: 1000')
}, 1000)
})
var p2 = new Promise((resolve, reject) => {
setTimeout(function(){
reject('p2: 2000')
}, 2000)
})
var p3 = new Promise((resolve, reject) => {
setTimeout(function(){
reject('p3: 3000')
}, 3000)
})
var p = Promise.all([p1, p2, p3]);
p.then(res => console.log('res', res))
.catch(err => console.log('err', err))
var p1 = new Promise((resolve, reject) => {
setTimeout(function(){
resolve('p1: 1000')
}, 1000)
})
var p2 = new Promise((resolve, reject) => {
setTimeout(function(){
reject('p2: 2000')
}, 2000)
})
var p = Promise.race([p1, p2]);
p.then(res => console.log('res', res))
.catch(err => console.log('err', err))
var p1 = new Promise((resolve, reject) => {
setTimeout(function(){
reject('p1: 1000')
}, 1000)
})
var p2 = new Promise((resolve, reject) => {
setTimeout(function(){
reject('p2: 2000')
}, 2000)
})
var p = Promise.race([p1, p2]);
p.then(res => console.log('res', res))
.catch(err => console.log('err', err))
var thenable = {
then: function (resolve, reject) {
resolve(1);
}
}
var p = Promise.resolve(thenable)
p.then(function(value) {
console.log(value)
})
setTimeout(function() {
console.log(2);
})
Promise.resolve().then(function() {
console.log(1);
})
console.log(3);
E12 新增的 Promise 的方法
// 当有成功的时候,返回最快那个成功
function fn(time, isResolve) {
return new Promise((resolve, reject) => {
setTimeout(() => {
isResolve ? resolve(`${time}毫秒后我成功啦!!!`) : reject(`${time}毫秒后我失败啦!!!`)
}, time)
})
}
Promise.any([fn(2000, true), fn(3000), fn(1000, true)]).then(res => {
console.log(res) // 1秒后 输出 1000毫秒后我成功啦
}, err => {
console.log(err)
})
// 当全都失败时
function fn(time, isResolve) {
return new Promise((resolve, reject) => {
setTimeout(() => {
isResolve ? resolve(`${time}毫秒后我成功啦!!!`) : reject(`${time}毫秒后我失败啦!!!`)
}, time)
})
}
Promise.any([fn(2000), fn(3000), fn(1000)]).then(res => {
console.log(res)
}, err => {
console.log(err) // 3秒后 报错 all Error
})
const PENDING = 'PENDING',
FULFILLED = 'FULFILLED',
REJECTED = 'REJECTED'; // 三种状态
class MyPromise {
constructor(executor) { // 实例化时传参:executor 执行器
this.status = PENDING;
this.value = undefined;
this.reason = undefined;
this.onFulfilledCallbacks = []; // 订阅池
this.onRejectedCallbacks = [];
const resolve = (value) => {
// 处理 resolve 传入的值也是 Promise 的情况
if (value instanceof MyPromise) {
value.then(resolve, reject);
return; // 递归调用,阻止向下继续执行
}
if (this.status === PENDING) {
// 必须得在 status 为 PENDING 状态下时,才能改变状态
this.status = FULFILLED;
this.value = value;
// 发布
this.onFulfilledCallbacks.forEach(fn => fn());
}
};
const reject = (reason) => {
if (this.status === PENDING) {
this.status = REJECTED;
this.reason = reason;
// 发布
this.onRejectedCallbacks.forEach(fn => fn());
}
};
try {
executor(resolve, reject);
} catch (err) {
// 如果在 executor 中直接抛出错误,得用 try-catch 捕获下,并走 reject
reject(err);
}
}
then(onFulfilled, onRejected) {
// 防止 .then() 不传参
onFulfilled = typeof onFulfilled === 'function' ? onFulfilled : value => value;
onRejected = typeof onRejected === 'function' ? onRejected : reason => { throw reason };
// then 每次都返回一个新的 Promise
let promise2 = new MyPromise((resolve, reject) => {
if (this.status === FULFILLED) {
setTimeout(() => {
try {
let x = onFulfilled(this.value);
// onFulfilled 有可能返回一个普通值,也有可能返回一个 Promise
// 所以需要一个函数来判断和处理这个返回值 x
resolvePromise(promise2, x, resolve, reject);
} catch (err) {
reject(err);
}
}, 0);
}
if (this.status === REJECTED) {
setTimeout(() => {
try {
let x = onRejected(this.reason);
resolvePromise(promise2, x, resolve, reject);
} catch (err) {
reject(err);
}
}, 0);
}
if (this.status === PENDING) {
// 订阅
this.onFulfilledCallbacks.push(() => {
// PENDING状态下回调也要异步
setTimeout(() => {
try {
let x = onFulfilled(this.value);
resolvePromise(promise2, x, resolve, reject);
} catch (err) {
reject(err);
}
}, 0);
});
this.onRejectedCallbacks.push(() => {
setTimeout(() => {
try {
let x = onRejected(this.reason);
resolvePromise(promise2, x, resolve, reject);
} catch (err) {
reject(err);
}
}, 0);
});
}
});
return promise2;
}
// catch() 相当于.then(null, () => {})
catch(errorCallback) {
return this.then(null, errorCallback);
}
// 1. finally 无论外边的Promise成功还是失败,都要走finally的回调,并且回调不带参数
// 2. finally 不返回 Promise 时, 走 then 或者 catch 取决于外边 Promise
// 3. 如果 finally 内部有 promise 并且有延迟处理,整个finally会等待
// 4. finally的promise如果是reject,优先级更高
// 5. finally的promise如果是resolve,则外边优先级更高
finally(finallyCallback) {
// finally是实例方法,得 return this.then
return this.then(value => {
// finally 能执行异步,所以 return 一个 MyPromise.resolve
// finally 本身没有状态
// 所以执行完cb后,再调用 then 返回 finally 之前的 resolve 情况下的 value
return MyPromise.resolve(finallyCallback()).then(() => value);
}, reason => {
// onRejected也得调用 MyPromise.resolve
// 因为 finally本身不影响外边的状态
// 在 finally 中return Promise 且 返回 rejected 的情况下
// MyPromise.resolve一个rejected的Promise,最终状态也会是这个新的Promise的rejected状态
return MyPromise.resolve(finallyCallback()).then(() => {
throw reason;
});
});
}
// Promise 的 静态方法 resolve、reject
static resolve(value) {
if (value instanceof MyPromise) {
return value;
}
return new MyPromise((resolve, reject) => {
resolve(value);
});
}
static reject(reason) {
return new MyPromise((resolve, reject) => {
reject(reason);
});
}
static all(promiseArr) {
let resArr = [],
count = 0;
return new MyPromise((resolve, reject) => {
promiseArr.map((promise, index) => {
if (isPromise(promise)) {
promise.then(value => {
formatResArr(value, index, resolve);
}, reject);
} else {
formatResArr(promise, index, resolve);
}
});
});
// value是返回值,index是数组索引,resolve是回调
function formatResArr(value, index, resolve) {
resArr[index] = value; // 保证结果和数组顺序一致
if(++count === promiseArr.length) { // 保证全部结果都成功返回后再返回最终结果
resolve(resArr);
}
}
}
static allSettled(promiseArr) {
if (!isIterator(promiseArr)) {
throw new TypeError(promiseArr + ' is not iterable (cannot read property Symbol(Symbol.iterator))');
}
let resArr = [],
count = 0;
return new MyPromise((resolve, reject) => {
// 数组为空的时候,返回空数组
if (promiseArr.length === 0) {
resolve([]);
} else {
promiseArr.map((promise, index) => {
if (isPromise(promise)) {
promise.then(value => {
formatResArr('fulfilled', value, index, resolve);
}, reason => {
formatResArr('rejected', reason, index, resolve);
});
} else {
formatResArr('fulfilled', promise, index, resolve);
}
});
}
});
function formatResArr(status, value, index, resolve) {
switch (status) {
case 'fulfilled':
resArr[index] = {
status,
value
}
break;
case 'rejected':
resArr[index] = {
status,
reason: value
}
break;
default:
break;
}
if (++count === promiseArr.length) {
resolve(resArr);
}
}
}
static race(promiseArr) {
return new MyPromise((resolve, reject) => {
if (promiseArr.length === 0) {
resolve();
} else {
promiseArr.map(promise => {
// if (isPromise(promise)) {
// promise.then(resolve, reject);
// } else {
// resolve(promise);
// }
MyPromise.resolve(promise).then(resolve, reject);
});
}
});
}
static any(promiseArr) {
if (!promiseArr.length) throw new Error('No Promise passed');
return new MyPromise((resolve, reject) => {
let count = 0, errors = [];
promiseArr.forEach((promise, idx) => {
MyPromise.resolve(promise).then(resolve).catch(err => {
errors[idx] = err;
if (++count === promiseArr.length) {
reject(new Error('No Promise in Promise.any was resolved'))
}
})
});
});
}
}
// 判断是否为 Promise
function isPromise(x) {
if ((typeof x === 'object' && x !== null) || typeof x === 'function') {
let then = x.then;
return typeof then === 'function';
}
return false;
}
// 判断是否为可迭代对象
function isIterator(value) {
return value !== undefined && value !== null && typeof value[Symbol.iterator] === 'function';
}
function resolvePromise(promise2, x, resolve, reject) {
if (promise2 === x) {
reject(new TypeError('Chaining cycle detected for promise #<MyPromise>'));
}
let called = false; // 防止 resolve、reject 都调用的情况
if ((typeof x === 'object' && x !== null) || typeof x === 'function') {
try { // 防止 then 抛错 throw Error
let then = x.then;
if (typeof then === 'function') { // 认定为 Promise
then.call(x, y => {
if (called) return;
called = true;
resolvePromise(promise2, y, resolve, reject);
}, r => {
if (called) return;
called = true;
reject(r);
});
} else {
resolve(x);
}
} catch(err) {
if (called) return;
called = true;
reject(err);
}
} else {
resolve(x);
}
}
MyPromise.defer = MyPromise.deferred = function() {
let deferred = {};
deferred.promise = new MyPromise((resolve, reject) => {
deferred.resolve = resolve;
deferred.reject = reject;
});
return deferred;
}
module.exports = MyPromise;
const fs = require('fs');
fs.readFile('./index.text', 'utf-8', (err, data) => {
if (err) {
console.log(err);
} else {
console.log(data);
}
});
const fs = require('fs');
const bluebird = require('bluebird');
const readFile = bluebird.promisify(fs.readFile);
readFile('./index.test', 'utf-8').then(value => {
console.log(value);
}, reason => {
console.log(reason);
});
module.exports = {
function promisify(fn) {
return function(...args) {
return new Promise((resolve, reject) => {
fn.call(null, ...args, (err, data) => {
if (err) {
reject(err);
} else {
resolve(data);
}
});
});
}
},
function promisifyAll(fns) {
Object.keys(fns).map(fnName => {
if (typeof fns[fnName] === 'function') {
fns[fnName + 'Async'] = this.promisify(fns[fnName]);
}
});
return fns;
}
}
const fs = require('fs');
const util = require('./util');
const readFile = util.promisify(fs.readFile);
readFile('./data/user.json', 'utf-8').then(value => {
console.log('value', value);
}, reason => {
console.log('reason', reason);
});
const fsFunctions = util.promisifyAll(fs);
fsFunctions.readFileAsync('./data/class.json', 'utf-8').then(value => {
console.log('valueAsync', value);
}, reason => {
console.log('reasonAsync', reason);
});