LazyMan的Promise解法
背景
见上一篇。 面向对象的链式调用中,掺杂了 一个一部动作, 对于这种工作链, 是非同步执行的链。
LazyMan("Hank").sleep(1).eat("dinner")
同步执行的工作链中, 任何一个动作,即函数调用, 都是同步的, 可理解为普通的函数。
异步的工作链, 前提条件是工作链中,存在至少一个 动作是 异步的。 例如 sleep
Promise
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise
The
Promise
object is used for asynchronous computations. APromise
represents a value which may be available now, or in the future, or never.
A
Promise
is a proxy for a value not necessarily known when the promise is created. It allows you to associate handlers to an asynchronous action's eventual success value or failure reason. This lets asynchronous methods return values like synchronous methods: instead of the final value, the asynchronous method returns a promise for the value at some point in the future.
A
Promise
is in one of these states:
- pending: initial state, not fulfilled or rejected.
- fulfilled: meaning that the operation completed successfully.
- rejected: meaning that the operation failed.
A pending promise can either be fulfilled with a value, or rejected with a reason (error). When either of these happens, the associated handlers queued up by a promise's
then
method are called.
四大特性:
Promise.all(iterable) --- 我有一个愿望, 等待所有的我指定的愿望 Promise都实现, 我的才能实现。
Promise.race(iterable) --- 我有一个愿望,等待我所指定的愿望中,只要有一个实现, 我的愿望就实现。
Promise.reject(reason) --- 我有一个愿望, 注定不会实现。
Promise.resolve(value) --- 我有一个愿望, 注定要实现。
then特性:
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise/then
The
then()
method returns aPromise
. It takes up to two arguments: callback functions for the success and failure cases of thePromise
.
Syntax
p.then(onFulfilled[, onRejected]); p.then(function(value) { // fulfillment }, function(reason) { // rejection });Parameters
then
returns aPromise
which is determined by the input functions:
- If
onFulfilled
oronRejected
throws an error, or returns aPromise
which rejects,then
returns a rejectedPromise
.- If
onFulfilled
oronRejected
returns aPromise
which resolves, or returns any other value,then
returns a resolvedPromise
.
Chaining
The
then
method returns aPromise
which allows for method chaining.You can pass a lambda to
then
and if it returns a promise, an equivalentPromise
will be exposed to the subsequent then in the method chain. The below snippet simulates asynchronous code with thesetTimout
function.
If
onFulfilled
returns a promise, the return value ofthen
will be resolved/rejected by the promise.
function resolveLater(resolve, reject) { setTimeout(function () { resolve(10); }, 1000); } function rejectLater(resolve, reject) { setTimeout(function () { reject(20); }, 1000); } var p1 = Promise.resolve("foo"); var p2 = p1.then(function() { // Return promise here, that will be resolved to 10 after 1 second return new Promise(resolveLater); }); p2.then(function(v) { console.log("resolved", v); // "resolved", 10 }, function(e) { // not called console.log("rejected", e); }); var p3 = p1.then(function() { // Return promise here, that will be rejected with 20 after 1 second return new Promise(rejectLater); }); p3.then(function(v) { // not called console.log("resolved", v); }, function(e) { console.log("rejected", e); // "rejected", 20 });
解法
结合 then的链使用, 给出方案:
function _LazyMan(name) { this.promiseGetters = []; var makePromise = function () { var promiseObj = new Promise(function(resolve, reject){ console.log("Hi! This is " + name + "!"); resolve(); }) return promiseObj; } this.promiseGetters.push(makePromise); // 在各个Promise的then函数中,将任务序列穿起来 var self = this; var sequence = Promise.resolve(); // Promise.resolve 等价于 // var sequence = new Promise(function (resolve, reject) { // resolve(); // }) setTimeout(function(){ for (var i = 0; i < self.promiseGetters.length; i++) { var nowPromiseGetter = self.promiseGetters[i]; var thenFunc = (function (nowPromiseGetter) { return function () { return nowPromiseGetter() } })(nowPromiseGetter); sequence = sequence.then(thenFunc); }; }, 0); // 在下一个事件循环启动任务 } _LazyMan.prototype.eat = function(name) { var makePromise = function () { var promiseObj = new Promise(function(resolve, reject){ console.log("Eat " + name + "~"); resolve(); }) return promiseObj; } this.promiseGetters.push(makePromise); return this; // 实现链式调用 } _LazyMan.prototype.sleep = function(time) { var makePromise = function () { var promiseObj = new Promise(function(resolve, reject){ setTimeout(function(){ console.log("Wake up after " + time + "s!"); resolve(); }, time * 1000); }) return promiseObj; } this.promiseGetters.push(makePromise); return this; } /* 封装 */ function LazyMan(name){ return new _LazyMan(name); } LazyMan("Hank").sleep(1).eat("dinner")