我已经开发了几年的JavaScript,我根本不理解有关承诺的大惊小怪.
似乎我所做的只是改变:
api(function(result){
api2(function(result2){
api3(function(result3){
// do work
});
});
});
Run Code Online (Sandbox Code Playgroud)
无论如何,我可以使用像async这样的库,例如:
api().then(function(result){
api2().then(function(result2){
api3().then(function(result3){
// do work
});
});
});
Run Code Online (Sandbox Code Playgroud)
哪个代码更多,可读性更低.我没有在这里获得任何东西,它也不会突然神奇地"平坦".更不用说必须将事物转换为承诺.
那么,这里的承诺有什么大惊小怪?
像q这样的promise/defer库是如何实现的?我试图阅读源代码,但发现它很难理解,所以我认为如果有人能从高层次向我解释在单线程JS环境中用于实现promise的技术是多么好像Node和浏览器.
我对被抛出的不同术语感到困惑.根据我的理解,承诺可以是:
fulfilled
rejected
pending
settled
resolved
defer
Run Code Online (Sandbox Code Playgroud)
解决意味着解决了吗?还是意味着它实现了?什么是推迟的?
promise/a +规范第2.2.4条规定:
在执行上下文堆栈仅包含平台代码之前,不得调用onFulfilled或onRejected.
然后在笔记中说明:
这里的"平台代码"意味着引擎,环境和承诺实现代码.实际上,这个要求确保onFulfilled和onRejected异步执行,然后调用事件循环,然后调用新堆栈.
这样做的目的是确保当链中存在大量onFulfilled函数时,它们的执行不会导致线程阻塞吗?
或者在我不读的行之间还有其他什么东西吗?
最近,向我展示了一段代码,这些代码是在全栈开发人员访谈中被要求的。它涉及创建一个Promise,应聘者应在其中实现,将其传递给resolve函数,然后将2链接起来。
我试图非常天真地实现Promise只是为了使代码正常工作。创建了一个接受解析器函数的ctor,创建了一个then函数,该函数接受一个回调并返回Promise,并简单地在resolver函数上调用该回调。
class MyPromise {
constructor(resolver) {
this.resolver = resolver;
}
then(callback) {
const result = new MyPromise(callback);
this.resolver(callback);
return result;
}
}
promise = new MyPromise(
(result) => {
setTimeout(result(2), 500);
});
promise.then(result => {
console.log(result);
return 2 * result;
}).then(result => console.log(result));
Run Code Online (Sandbox Code Playgroud)
预期结果是2,4-就像在真正的Promise上运行一样。但是我得到了2,2。我在弄清楚如何获取第一个“ then”的返回值并将其传递时遇到了麻烦。
我所指的规范是http://promises-aplus.github.io/promises-spec/.
使用时then(),您可以返回一个承诺,并在您希望时拒绝承诺,或者您可以抛出异常拒绝承诺.
为什么api不是以这种方式设计的,对于then函数来说,它是像原始的promise构造函数一样传递一个解析和拒绝函数?
许多语言中的异常都很繁重(我也假设在javascript中),所以看起来很奇怪他们将它们用作流控制的选择.创建一个全新的promise对象并返回它,只是为了拒绝它,增加了代码膨胀IMO.如果抛出异常(例如语法错误,或者在未定义的对象上调用函数等),调试也会变得更难.
做一些研究Promises,我知道一个Promise对象可以处于三种状态(待定、已解决、被拒绝)。负责这三种状态中的每一种的逻辑都在传递给Promise构造函数的回调函数中。这个回调函数有 2 个函数作为它的参数解析和拒绝,当这个回调导致成功或失败时调用它们。
在Promise实例化之后,我们可以通过调用.then它的函数向承诺添加响应处理程序回调。该.then函数将 2 个回调函数作为其参数。第一个参数是调用Promiseresolve函数时调用的回调Promise函数,调用reject函数时调用第二个回调函数。您也可以拨打.catch上Promises处理被拒绝的承诺,虽然这仅仅是语法糖:
.then(undefined, () => { failure callback})
Run Code Online (Sandbox Code Playgroud)
我发现更难理解的是该.then 方法返回一个 Promise. 例如在以下代码中:
.then(undefined, () => { failure callback})
Run Code Online (Sandbox Code Playgroud)
在第一个示例中,.then它返回 : nr + 5。在解决Promise此值的情况下成功传递到第二个.then。这怎么可能?它是在引擎盖下:
return new Promise((res,rej) => {
res(nr + 5)
})
Run Code Online (Sandbox Code Playgroud)
或者这是由其他原因引起的?
鉴于客户端程序员既定义又使用resolve传递给Promise的执行器的函数,我天真地假设我完全控制了resolve函数的签名,因此我可以定义它接受多个参数。
然而以下代码(jsFiddle)失败了:
<html>
<script>
const promise = new Promise(function executor(resolve, reject) {
setTimeout(function () {
resolve(42, true);
}, 1000);
});
promise.then(function resolveCallback(answer, howCertain) {
console.log('callback called with arguments: ('+answer+', '+howCertain+')');
console.log('the answer is: '+answer+'. I am '+(howCertain?'very':'not very')+' certain about that');
});
</script>
</html>
Run Code Online (Sandbox Code Playgroud)
上面的代码实际上打印在控制台上:
callback called with arguments: (42, undefined)
the answer is: 42. I am not very certain about that
Run Code Online (Sandbox Code Playgroud)
再深入一点,我写了下面的代码(jsFiddle):
<html>
<script>
const promise = new Promise(function …Run Code Online (Sandbox Code Playgroud) 我正在尝试用.then()javascript 实现具有可链接功能的简单promise类。这是我到目前为止所做的-
class APromise {
constructor(Fn) {
this.value = null;
Fn(resolved => { this.value = resolved; });
}
then(fn) {
fn(this.value);
return this;
}
}
function myFun() {
return new APromise(resolve => {
// just resolve('Hello'); works but this doesn't
setTimeout(() => { resolve('Hello'); }, 2000);
});
}
const log = v => { console.log(v); };
myFun().then(log).then(log);
Run Code Online (Sandbox Code Playgroud)
输出-
null
null
Run Code Online (Sandbox Code Playgroud)
Instead of 'Hello' 2 times. I think it is currently ignoring setTimeout() call, how should I make this …
javascript ×9
promise ×8
callback ×2
es6-promise ×2
node.js ×2
bluebird ×1
ecmascript-6 ×1
event-loop ×1
q ×1