Promise asynchronous processing

Promise of state

Promise is one of asynchronous programming solutions compared to traditional callback (callback solve hell) and event mechanism more reasonable and powerful.
Promise Examples of three states:

  • Pending: Ongoing
  • Resolved: I Completed
  • Rejected: Failed

Examples of state only by Promise Pending-> Resolved, Pending-> Rejected. Once the status is changed Promise instance, can not be changed.

Uncontrollable state

Once created Promise, will be executed immediately, not be canceled.
While in pending state, the process can not know specific information, such as percent complete (although you can set your own callback notification).

Failed state

The state can only turn into a success by the resolve method.
Failed state can be converted into a reject method, may be transferred indirectly to the error is thrown.

1
2
3
4
5
6
7
8
9
10
11
12
13
Three would normally print out information failed.

new Promise((resolve, reject) => {
reject('error');
}).catch(console.log); // error

new Promise((resolve, reject) => {
a;
}).catch(console.log); // ReferenceError: a is not defined

new Promise((resolve, reject) => {
throw 'error';
}).catch(console.log); // Error: error

Error reporting mechanism

If it fails the state does not receive the failed callback function receives, Promise will throw an error.
Here's throw errors, just like the console prompt of the display, the process will not terminate the program.

1
2
3
4
5
6
7
8
9
Print out 'ERR' , again being given.

new Promise((resolve, reject) => {
reject();
});

new Promise((resolve, reject) => {
reject('err');
}).then(() => {}, console.log);

Once Promise set up a callback function fails, even code execution errors will be self-digestion, nothing more than newspaper.

1
2
3
4
5
Although a not defined, but the whole quiet, slotless point.

new Promise((resolve, reject) => {
a;
}).then(() => {}, () => {});

Promise Constructor

Promise is a constructor, for instance generates Promise

1
2
3
4
5
6
7
8
var Promise = new new  Promise ( function ( Resolve, Reject )) { IF ( / * asynchronous operation results * / ) {         Resolve (value)     } the else { / * asynchronous operation failed * /         Reject (error)     } }







Execution order

Incoming method
to create the Promise will also perform passed to the method.
Incoming calls the method will not be a way to resolve / reject terminates execution, it is better retrun resolve / reject.

1
2
3
4
5
6
7
Print out 1  2 

new Promise((resolve, reject) => {
console.log(1);
resolve();
console.log(2);
});

Callback method
immediate result of Promise, which is the callback function will still be later than the current round of event execution.
Unlike setTimeout perform this function is executed after the execution stack to push, but the function will be executed at the end of the round into.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
The result obtained is: . 1  2  . 3  . 4  . 5  . 6 

console.log(1);

setTimeout(() => {
console.log(5);
});

let p = new Promise((resolve, reject) => {
console.log(2);
resolve();
});


p.then(function() {
console.log(4);
});

setTimeout(() => {
console.log(6);
});

console.log(3);

执行顺序涉及到JS的运行机制(事件循环)
macro-task:script(整体代码), setTimeout, setInterval, setImmediate, I/O, UI rendering。
micro-task:process.nextTick, Promises, Object.observe, MutationObserver
执行顺序:函数调用栈清空只剩全局执行上下文,然后开始执行所有的micro-task。当所有可执行的micro-task执行完毕之后。循环再次执行macro-task中的一个任务队列,执行完之后再执行所有的micro-task,就这样一直循环。

事件循环机制呢,简单点来说,就是在执行上下文的过程中,对函数的入栈和出栈。执行前函数先入栈,执行完后函数出栈。如若遇到了一些异步操作像回调函数以及ajax、setTimeout,Promise等,会先将他们交给浏览器的其他模块去执行,执行完后,会把回调函数放入到taskqueue中。当所有的call stack执行完后再开始执行task queue中的函数。

我们知道,Promise的回调函数不是传入的,而是使用then来调用的。因此,Promise中定义的函数应该是马上执行的,then才是其回调函数,放入queue队列中。

具体的过程可以看上面那篇文章。大概过程如下:

  1. 主线程同步任务console.log(1);直接打印 1
  2. 遇到setTimeout,交给其他模块执行,执行完后回调放入macro-task中
  3. 遇到Promise,立即执行里面的function,打印 2。
  4. 循环开始,遇到resolve(),修改Promise状态为fulfill。继续执行。
  5. 遇到then,将回调放入micro-task中。
  6. 遇到setTimeout,交给其他模块执行,执行完后回调放入macro-task中
  7. 主线程同步任务console.log(3);直接打印 3
  8. call stack执行完毕了。开始执行micro-task中的回调函数,输出 4。
  9. micro-task执行完毕,开始执行macro-task中的回调函数,分别输出5,6。
  10. 结束(输出结果是:1 2 3 4 5 6)

结果参数

传入reject的参数,一般是字符串或Error实例,表示抛出的错误。
传入resolve的参数,一般是相应的JSON数据等,表示得到的数据。

传入resolve的参数,还可以是另一个Promise实例。
这时,只有当内层的Promise结束后,外层的Promise才会结束。

1
2
3
4
5
6
7
8
9
10
11
12
13
过两秒后,打印出 2000 

new Promise((resolve, reject) => {
resolve(createPromise());
}).then(console.log);

function () {
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve(2000);
}, 2000);
});
}

在这种情况下,如果内层失败,并不等于传递Error实例给resolve不同。
前者是内层Promise抛出了错误将被外层捕获,后者仅仅是参数为一个Error实例。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
内层失败的信息,被外层捕获。过两秒,打印出 '2' 2000 

new Promise((resolve, reject) => {
resolve(createPromise());
}).then(res => {
console.log('1', res);
}, err => {
console.log('2', err);
});

function () {
return new Promise((resolve, reject) => {
setTimeout(() => {
reject(2000);
}, 2000);
});
}

实例方法

then()

该方法可传入两个,分别对应成功/失败时的回调函数。
该方法返回的是一个新的Promise对象,这也是可以使用链式(.then.then…)的原因。

1
2
3
let p1 = new Promise(resolve => resolve(2000));
let p2 = p1.then(() => {}, () => {});
console.log(p1 === p2); // false

return
链式中,后者的状态取决于前者(成功/失败)的回调函数中返回(return)的结果。
如果没有返回,相当返回一个成功的状态,值为undefined。
如果返回为Promise对象,后者的状态由该对象的最终状态决定。
如果返回为非Promise对象的数据,相当返回一个成功的状态,值为此数据。
如果前者执行时抛出了错误,相当是返回一个失败的状态,值为此错误。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
依次打印出:
1 res 2000
2 res undefined
3 res 3000
4 err 4000

new Promise(resolve => resolve(2000))
.then(res => {
console.log('1 res', res);
})
.then(res => {
console.log('2 res', res);
return 3000;
})
.then(res => {
console.log('3 res', res);
return new Promise((resolve, reject) => {
reject(4000);
});
})
.then(console.log, err => {
console.log('4 err', err);
});

状态的传递
在链式中,如果前者的状态没有被后者捕获,会一直冒泡到被捕获为止。
状态被捕获后便消失,这之后的的状态由当前then返回的状态决定,之后重复。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
依次打印出:
2 res 2000
3 res 3000

new Promise(resolve => resolve(2000))
.then(null, err => {
console.log('1 err', err);
})
.then(res => {
console.log('2 res', res);
return 3000;
})
.then(res => {
console.log('3 res', res);
});

catch()

用于指定发生错误时的回调函数,等价于:.then(null, callback)。
其表现与then一致,比如返回新的Promise,状态的继承和传递等等。

一般推荐使用catch而不是then的第二个方法接收错误。
因为catch可以捕获then自身的错误,也更接近同步的写法(try/catch)。

1
2
3
4
5
6
7
new Promise(() => {})
.then(() => {
...
})
.catch(() => {
...
});

finally()

用于Promise处理结束后的收尾工作。
传入其的回调函数不会接受任何参数,意味着没有办法知道Promise的结果。
这也正表明,finally里面的操作与状态无关,不依赖Promise的处理结果。

其本质和catch一样,也是then方法的变种。
不过其仅仅是状态的传递者,只会返回原状态,不会接收状态和创建新的状态。

1
2
3
4
5
6
7
8
9
10
11
12
13
p.finally(() => {
// codes...
});

--- 等价于

p.then(res => {
// codes...
return res; // 将原成功状态返回
}, err => {
// codes...
throw err; // 将原失败状态返回
});

e.g. 在请求数据时,我们会显示加载图案,请求完成后无论结果都要隐藏此图案。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
一般,一个完整的 Promise 的结构会如下。

showLoading = true;

new Promise((resolve, reject) => {
// 请求...
})
.then(res => {
// 成功处理...
})
.catch(err => {
// 失败处理...
})
.finally(() => {
// 重置一些状态...
showLoading = false;
});

静态方法

resolve()

此方法直接返回一个状态为resolved,值为其参数的Promise。

1
2
3
Promise.resolve(res);
--- 等价于
new Promise(resolve => resolve(res));

reject()

此方法直接返回一个状态为rejected,值为其参数的Promise。

1
2
3
Promise.reject(res);
--- 等价于
new Promise((resolve, reject) => reject(res));

all()

此方法用于将多个Promise实例,包装成一个新的Promise实例。
其参数为一个数组,每一项应为Promise实例(不是则会使用Promise.resolve进行转化)。

新Promise的状态取决于传入数组中的每一项的最终状态。
如果有一项状态变成rejected,新实例则为rejected,值为该项的返回值。
如果全部项都变成了resolved,新实例则为resolved,值为包含每一项返回值的数组。

1
2
3
4
5
6
7
8
9
10
11
三秒后,打印出:[1, 2, 3]。

let pArr = [1, 2, 3].map(createPromise);

Promise.all(pArr).then(console.log);

function (num) {
return new Promise((resolve, reject) => {
setTimeout(() => { resolve(num) }, num * 1000);
});
}

race()

此方法与all()基本相同,传入的参数也是一个Promise数组。 (取决于第一个状态)
不同的是,新Promise的最终状态是由数组中第一个状态改变的项(成功或失败)决定的。

1
2
3
4
5
6
7
8
9
10
11
结果:Error: time out  
var p = Promise.race([
new Promise(resolve => {
setTimeout(() => resolve('p1'), 10000);
}),
new Promise((resolve, reject) => {
setTimeout(() => reject(new Error('time out')), 10);
})
]);
p.then( ret => console.log(ret))
.catch( err => console.log(err.toString()));

Original: Big Box  Promise asynchronous processing


Guess you like

Origin www.cnblogs.com/petewell/p/11612103.html
Recommended