编辑,更新
删除了“嵌套”ternary
模式;添加
- a)
dfd.err()
,.catch()
处理Promise.reject(/* reason ? */)
arguments
传递给dfd.fn()
;
- b)
args === ""
在dfd.process()
处理范围内""
:空String
传递argument
给dfd.fn()
- c) 替代“链接”
.then()
要求then.apply(dfd.promise, [contactExists, getFirstContact])
本机Error()
传递为argument
:dfd.fn(new Error("error"))
在global
范围内处理;dfd.fn()
仍然返回dfd.promise
。可能会在 或 之前调整dfd.process()
,以“早”返回Error
或传递Error
到dfd.err()
; 根据要求。下文不再赘述js
。
尝试
var dfd = {
// set `active` : `false`
"active": false,
// set `promise`: `undefined`
"promise": void 0,
// process `arguments`, if any, passed to `dfd.fn`
"process": function process(args) {
// return `Function` call, `arguments`,
// or "current" `dfd.promise`;
// were `args`:`arguments` passed ?
// handle `""` empty `String` passed as `args`
return args === "" || !!args
// if `args`:`Function`, call `args` with `this`:`dfd`,
// or, set `args` as `value`, `reason`
// of "next" `dfd.promise`
// return "next" `dfd.promise`
? args instanceof Function && args.call(this) || args
// set `dfd.active`:`false`
// when "current" `dfd.promise`:`Promise` `fulfilled`,
// return "current" `dfd.promise`
: this.active = true && this.promise
},
// handle `fulfilled` `Promise.reject(/* `reason` ? */)`,
// passed as `args` to `dfd.fn`
"err": function err(e) {
// notify , log `reason`:`Promise.reject(/* `reason` ? */)`, if any,
// or, log `undefined` , if no `reason` passed: `Promise.reject()`
console.log("rejected `Promise` reason:", e || void 0);
},
// do stuff
"fn": function fn(args /* , do other stuff */) {
// set `_dfd` : `this` : `dfd` object
var _dfd = this;
// if "current" `dfd.promise`:`Promise` processing,
// wait for `fulfilled` `dfd.promise`;
// return `dfd.promise`
_dfd.promise = !_dfd.active
// set, reset `dfd.promise`
// process call to `dfd.async`;
// `args`:`arguments` passed to `dfd.fn` ?,
// if `args` passed, are `args` `function` ?,
// if `args` `function`, call `args` with
// `this`:`dfd`;
// or, return `args`
? _dfd.process(args)
// if `_dfd.active`, `_dfd.promise` defined,
// return "current" `_dfd.promise`
: _dfd.promise.then(function(deferred) {
// `deferred`:`_dfd.promise`
// do stuff with `deferred`,
// do other stuff,
// return "current", "next" `deferred`
return deferred
})
// handle `args`:`fulfilled`,
// `Promise.reject(/* `reason` ? */)`
.catch(_dfd.err);
return Promise.resolve(_dfd.promise).then(function(data) {
// `data`:`undefined`, `_dfd.promise`
// set `_dfd.active`:`false`,
// return `value` of "current", "next" `_dfd.promise`
_dfd.active = false;
return data
})
// handle `fulfilled` `Promise.reject(/* `reason` ? */),
// if reaches here ?
.catch(_dfd.err)
}
};
function log() {
var args = Array.prototype.slice.call(arguments).join(", ");
console.log(args);
var output = document.getElementById('output');
output.innerHTML += args + "<br/>";
};
var dumpContacts = function () {
log('Calling back-end to get contact list.');
return new Promise(function (resolve, reject) {
setTimeout(function () {
log('New data received from back-end.');
resolve(["Mary", "Frank", "Klaus"]);
}, 3000);
});
};
var getContacts = function () {
return dfd.async().then(function (contacts) {
for (var i = 0; i < contacts.length; i++) {
log("Contact " + (i + 1) + ": " + contacts[i]);
}
});
};
var contactExists = function (contactName) {
return dfd.async().then(function (contacts) {
return contacts.indexOf(contactName) >= 0 ? true : false;
});
};
var getFirstContact = function () {
return dfd.async().then(function (contacts) {
if (contacts.length > 0) {
return contacts[0];
}
return contacts
});
};
// Test:
// Show all contacts
dfd.async(dumpContacts)
.then(getContacts)
.then.apply(dfd.promise, [
// Does contact 'Jane' exist?
contactExists("Jane").then(function (exists) {
log("Contact 'Jane' exist: " + exists);
})
, getFirstContact().then(function (firstContact) {
log("first contact: " + firstContact);
})
]);
function log() {
var args = Array.prototype.slice.call(arguments).join(", ");
console.log(args);
var output = document.getElementById('output');
output.innerHTML += args + "<br/>";
return output
};
var dfd = {
"active": false,
"promise": void 0,
"process": function process(args) {
return args === "" || !!args
? args instanceof Function && args.call(this) || args
: this.active = true && this.promise
},
"err": function err(e) {
console.log("rejected `Promise` reason:", e || void 0);
},
"fn": function fn(args) {
var _dfd = this;
_dfd.promise = !_dfd.active
? _dfd.process(args)
: _dfd.promise.then(function(deferred) {
return deferred
})
.catch(_dfd.err);
return Promise.resolve(_dfd.promise).then(function(data) {
_dfd.active = false;
return data
})
.catch(_dfd.err)
}
};
var dumpContacts = function() {
log('Calling back-end to get contact list.');
return new Promise(function(resolve, reject) {
setTimeout(function() {
log('New data received from back-end.');
resolve(["Mary", "Frank", "Klaus"]);
}, 3000);
});
};
var getContacts = function() {
return dfd.fn().then(function(contacts) {
for (var i = 0; i < contacts.length; i++) {
log("Contact " + (i + 1) + ": " + contacts[i]);
}
});
};
var contactExists = function(contactName) {
return dfd.fn().then(function(contacts) {
return contacts.indexOf(contactName) >= 0 ? true : false;
});
};
var getFirstContact = function() {
return dfd.fn().then(function(contacts) {
if (contacts.length > 0) {
return contacts[0];
}
return contacts
});
};
// Test:
// Show all contacts
dfd.fn(dumpContacts)
.then(getContacts)
.then(function() {
// Does contact 'Jane' exist?
return contactExists("Jane").then(function(exists) {
log("Contact 'Jane' exist: " + exists);
})
})
.then(function() {
return getFirstContact().then(function(firstContact) {
log("first contact: " + firstContact);
})
});
<body>
Must use browser that supportes the Promises API, such as Chrome
<div id='output'>
<br/>
</div>
<hr>
</body>