JavaScript是单线程的,这意味着两个脚本不能同时运行;他们必须一个接一个地跑。 Promise是一个对象,表示异步操作的最终完成(或失败)及其结果值。
var promise = new Promise(function(resolve, reject) {
// do thing, then…
if (/* everything worked */) {
resolve("See, it worked!");
}
else {
reject(Error("It broke"));
}
});
承诺存在于其中一种状态中
- 待定:初始状态,既未履行也未拒绝。
- 实现:操作成功完成。
- 拒绝:操作失败。
Promise对象用作创建promise时未必知道的值的代理。它允许您将处理程序与异步操作的最终成功值或失败原因相关联。这允许异步方法返回类似于同步方法的值:异步方法返回一个承诺,在将来的某个时刻提供值,而不是立即返回最终值。
使用'然后'(承诺链接)
要进行多次异步调用并依次同步它们,可以使用promise chaining。这允许在后面的后续回调中使用第一个promise中的值。
Promise.resolve('some')
.then(function(string) { // <-- This will happen after the above Promise resolves (returning the value 'some')
return new Promise(function(resolve, reject) {
setTimeout(function() {
string += 'thing';
resolve(string);
}, 1);
});
})
.then(function(string) { // <-- This will happen after the above .then's new Promise resolves
console.log(string); // <-- Logs 'something' to the console
});
承诺API
Promise类中有4个静态方法:
- Promise.resolve
- Promise.reject
- Promise.all
- Promise.race
承诺可以链接在一起
编写Promise来解决特定问题时,可以将它们链接在一起形成逻辑。
var add = function(x, y) {
return new Promise((resolve,reject) => {
var sum = x + y;
if (sum) {
resolve(sum);
}
else {
reject(Error("Could not add the two values!"));
}
});
};
var subtract = function(x, y) {
return new Promise((resolve, reject) => {
var sum = x - y;
if (sum) {
resolve(sum);
}
else {
reject(Error("Could not subtract the two values!"));
}
});
};
// Starting promise chain
add(2,2)
.then((added) => {
// added = 4
return subtract(added, 3);
})
.then((subtracted) => {
// subtracted = 1
return add(subtracted, 5);
})
.then((added) => {
// added = 6
return added * 2;
})
.then((result) => {
// result = 12
console.log("My result is ", result);
})
.catch((err) => {
// If any part of the chain is rejected, print the error message.
console.log(err);
});
这对于遵循_功能编程_范例很有用。通过创造 用于操纵数据的函数可以将它们链接在一起以组装最终数据 结果。如果在函数链中的任何一点,一个值被_拒绝_链 将跳到最近的catch()
处理程序。
函数发生器
在最近的版本中,JavaScript引入了更多本机处理Promises的方法。一种这样的方法是函数发生器。函数发生器是“可暂停”的函数。与Promises一起使用时,生成器可以使用起来更容易阅读并显示为“同步”。
const myFirstGenerator = function* () {
const one = yield 1;
const two = yield 2;
const three = yield 3;
return 'Finished!';
}
const gen = myFirstGenerator();
这是我们的第一个生成器,您可以通过function*
语法看到它。我们声明的gen
变量不会运行myFirstGenerator
,而是“此生成器可以使用”。
console.log(gen.next());
// Returns { value: 1, done: false }
当我们运行gen.next()
,它将取消暂停生成器并继续运行。由于这是我们第一次调用gen.next()
,它将运行yield 1
并暂停,直到我们再次调用gen.next()
。当调用yield 1
,它将返回给我们产生的value
以及生成器是否done
。
console.log(gen.next());
// Returns { value: 2, done: false }
console.log(gen.next());
// Returns { value: 3, done: false }
console.log(gen.next());
// Returns { value: 'Finished!', done: true }
console.log(gen.next());
// Will throw an error
当我们继续调用gen.next()
,它将继续进行下一次yield
并且每次都暂停。一旦没有剩余yield
,它将继续运行发电机的其余部分,在这种情况下只返回'Finished!'
。如果再次调用gen.next()
,它将在生成器完成时抛出错误。
现在,假设这个例子中的每个yield
都是Promise
,代码本身看起来非常同步。
Promise.all(iterable)对于对不同源的多个请求非常有用
Promise.all(iterable)方法返回单个Promise,当可迭代参数中的所有promise都已解析或者iterable参数不包含promise时,它将解析。它拒绝了第一个承诺拒绝的原因。
var promise1 = Promise.resolve(catSource);
var promise2 = Promise.resolve(dogSource);
var promise3 = Promise.resolve(cowSource);
Promise.all([promise1, promise2, promise3]).then(function(values) {
console.log(values);
});
// expected output: Array ["catData", "dogData", "cowData"]
更多JavaScript教程
学习更多JavaScript教程