ES6でのPromiseの使い方を詳しく解説

php中世界最好的语言
リリース: 2018-05-31 10:27:17
オリジナル
1169 人が閲覧しました

今回はES6でPromiseを使う際の注意点について詳しく解説していきます。

もちろん、これは爆発的にフルスタックになったという意味ではありません。スタック全体のスキルは非常に集中しており、フロントエンドが HTML と対話を作成できるだけでなく、バ​​ックエンドもデータベースの追加、削除、チェック、変更に精通しています。

Node に関わったことがある人なら誰でも、Node は非同期 (Async) コールバックで有名であることを知っているはずです。その非同期性により、プログラムの実行効率が向上しますが、プログラムの可読性も低下します。複数の非同期操作があり、後の操作では前の操作によって返されたデータを実行する必要がある場合、Node の一般的な実行ルールに従って、通常、順序付けられた非同期操作はレイヤーごとにネストされます。

この問題を解決するために、ES6 は Promise の実装を提案しました。

意味

Promise Object は、非同期操作の最終的な完了 (または失敗) とその結果値を表すために使用されます。簡単に言うと、非同期処理が成功した場合は、成功した処理が実行され、非同期処理が失敗した場合は、エラーが捕捉されるか、以降の処理が停止されます。

その一般的な表現は次のとおりです:

new Promise(
  /* executor */
  function(resolve, reject) {
    if (/* success */) {
      // ...执行代码
      resolve();
    } else { /* fail */
      // ...执行代码
      reject();
    }
  }
);
ログイン後にコピー

このうち、Promise のパラメータ executor は、resolve と accept の 2 つのパラメータを持つ executor 関数です。通常、内部にはいくつかの非同期操作が含まれています。非同期操作が成功した場合は、resolve() を呼び出してインスタンスの ステータス を設定できます。失敗した場合は、reject() を呼び出します。インスタンスの

ステータス

をフルフィルメントに設定します。ステータスは拒否、つまり失敗に設定されます。

    Promise オブジェクトは工場の組立ラインと考えることができます。組立ラインのジョブ機能から判断すると、そのジョブの状態は 3 つだけあり、1 つは初期状態 (電源が入ったばかりのとき) で、もう 1 つは初期状態です。 1 つは製品の処理が成功した場合、1 つは製品の処理が失敗した場合 (何らかの障害が発生した場合) です。同様に、Promise オブジェクトにも 3 つの状態があります:
  1. pending: 初期状態 (未決定状態とも呼ばれます) は、Promise の初期化時に executor executor 関数を呼び出した後の状態です。
  2. fulfilled: 完了ステータス。非同期操作が成功したことを意味します。
  3. rejected: 失敗ステータス。非同期操作が失敗したことを意味します。

    変換できる状態は 2 つだけです。つまり、
  1. 操作が成功しました: 保留中 -> 完了
  2. 操作が失敗しました: 保留中 -> 拒否されました

とこの状態変換これは一方向で不可逆的であり、決定された状態 (履行/拒否) を初期状態 (保留中) に戻すことはできません。 method

Promise.prototype.then()

Promise オブジェクトには then() が呼び出された後、Promise オブジェクトが返されます。つまり、インスタンス化された Promise オブジェクトはそして、この then() メソッドは 2 つの関数を受け取ることができます。1 つは処理が成功した後の関数で、もう 1 つはエラー結果を処理する関数です。

以下の通り:

var promise1 = new Promise(function(resolve, reject) {
 // 2秒后置为接收状态
 setTimeout(function() {
  resolve('success');
 }, 2000);
});
promise1.then(function(data) {
 console.log(data); // success
}, function(err) {
 console.log(err); // 不执行
}).then(function(data) {
 // 上一步的then()方法没有返回值
 console.log('链式调用:' + data); // 链式调用:undefined 
}).then(function(data) {
 // ....
});
ログイン後にコピー

ここでは主に、promise1.then() メソッドが呼び出された後に返される Promise オブジェクトのステータスに焦点を当てます。保留中、履行済み、または拒否済みですか?

    返される Promise オブジェクトのステータスは次のとおりです。主にpromise1をベースにしていますが、then()メソッドで返される値は以下の場合に大別されます。
  1. then()メソッドでパラメータ値が返された場合、返されたPromiseが受信状態になります。
  2. then() メソッドで例外がスローされた場合、返された Promise は拒否されます。
  3. then()メソッドがresolve()メソッドを呼び出すと、返されたPromiseが受信状態になります。
  4. then() メソッドが拒否() メソッドを呼び出すと、返された Promise は拒否されます。
  5. then() メソッドが不明な状態 (保留中) の新しい Promise インスタンスを返した場合、返された新しい Promise は不明な状態になります。
  6. then() メソッドで、resolve(data)/reject(data)/return data が明示的に指定されていない場合、返される新しい Promise は受信状態であり、レイヤーごとに受け渡すことができます。

🎜変換例は次のとおりです: 🎜
var promise2 = new Promise(function(resolve, reject) {
 // 2秒后置为接收状态
 setTimeout(function() {
  resolve('success');
 }, 2000);
});
promise2
 .then(function(data) {
  // 上一个then()调用了resolve,置为fulfilled态
  console.log('第一个then');
  console.log(data);
  return '2';
 })
 .then(function(data) {
  // 此时这里的状态也是fulfilled, 因为上一步返回了2
  console.log('第二个then');
  console.log(data); // 2
  return new Promise(function(resolve, reject) {
   reject('把状态置为rejected error'); // 返回一个rejected的Promise实例
  });
 }, function(err) {
  // error
 })
 .then(function(data) {
  /* 这里不运行 */
  console.log('第三个then');
  console.log(data);
  // ....
 }, function(err) {
  // error回调
  // 此时这里的状态也是fulfilled, 因为上一步使用了reject()来返回值
  console.log('出错:' + err); // 出错:把状态置为rejected error
 })
 .then(function(data) {
  // 没有明确指定返回值,默认返回fulfilled
  console.log('这里是fulfilled态');
});
ログイン後にコピー

Promise.prototype.catch()

catch()方法和then()方法一样,都会返回一个新的Promise对象,它主要用于捕获异步操作时出现的异常。因此,我们通常省略then()方法的第二个参数,把错误处理控制权转交给其后面的catch()函数,如下:

var promise3 = new Promise(function(resolve, reject) {
 setTimeout(function() {
  reject('reject');
 }, 2000);
});
promise3.then(function(data) {
 console.log('这里是fulfilled状态'); // 这里不会触发
 // ...
}).catch(function(err) {
 // 最后的catch()方法可以捕获在这一条Promise链上的异常
 console.log('出错:' + err); // 出错:reject
});
ログイン後にコピー

Promise.all()

Promise.all()接收一个参数,它必须是可以迭代的,比如数组

它通常用来处理一些并发的异步操作,即它们的结果互不干扰,但是又需要异步执行。它最终只有两种状态:成功或者失败。

它的状态受参数内各个值的状态影响,即里面状态全部为fulfilled时,它才会变成fulfilled,否则变成rejected。

成功调用后返回一个数组,数组的值是有序的,即按照传入参数的数组的值操作后返回的结果。如下:

// 置为fulfilled状态的情况
var arr = [1, 2, 3];
var promises = arr.map(function(e) {
 return new Promise(function(resolve, reject) {
  resolve(e * 5);
 });
});
Promise.all(promises).then(function(data) {
  // 有序输出
 console.log(data); // [5, 10, 15]
 console.log(arr); // [1, 2, 3]
});
ログイン後にコピー
// 置为rejected状态的情况
var arr = [1, 2, 3];
var promises2 = arr.map(function(e) {
 return new Promise(function(resolve, reject) {
  if (e === 3) {
   reject('rejected');
  }
  resolve(e * 5);
 });
});
Promise.all(promises2).then(function(data) {
 // 这里不会执行
 console.log(data);
 console.log(arr);
}).catch(function(err) {
 console.log(err); // rejected
});
ログイン後にコピー

Promise.race()

Promise.race()和Promise.all()类似,都接收一个可以迭代的参数,但是不同之处是Promise.race()的状态变化不是全部受参数内的状态影响,一旦参数内有一个值的状态发生的改变,那么该Promise的状态就是改变的状态。就跟race单词的字面意思一样,谁跑的快谁赢。如下:

var p1 = new Promise(function(resolve, reject) {
 setTimeout(resolve, 300, 'p1 doned');
});
var p2 = new Promise(function(resolve, reject) {
 setTimeout(resolve, 50, 'p2 doned');
});
var p3 = new Promise(function(resolve, reject) {
 setTimeout(reject, 100, 'p3 rejected');
});
Promise.race([p1, p2, p3]).then(function(data) {
 // 显然p2更快,所以状态变成了fulfilled
 // 如果p3更快,那么状态就会变成rejected
 console.log(data); // p2 doned
}).catch(function(err) {
 console.log(err); // 不执行
});
ログイン後にコピー

Promise.resolve()

Promise.resolve()接受一个参数值,可以是普通的值,具有then()方法的对象和Promise实例。正常情况下,它返回一个Promise对象,状态为fulfilled。但是,当解析时发生错误时,返回的Promise对象将会置为rejected态。如下:

// 参数为普通值
var p4 = Promise.resolve(5);
p4.then(function(data) {
 console.log(data); // 5
});
// 参数为含有then()方法的对象
var obj = {
 then: function() {
  console.log('obj 里面的then()方法');
 }
};
var p5 = Promise.resolve(obj);
p5.then(function(data) {
 // 这里的值时obj方法里面返回的值
 console.log(data); // obj 里面的then()方法
});
// 参数为Promise实例
var p6 = Promise.resolve(7);
var p7 = Promise.resolve(p6);
p7.then(function(data) {
 // 这里的值时Promise实例返回的值
 console.log(data); // 7
});
// 参数为Promise实例,但参数是rejected态
var p8 = Promise.reject(8);
var p9 = Promise.resolve(p8);
p9.then(function(data) {
 // 这里的值时Promise实例返回的值
 console.log('fulfilled:'+ data); // 不执行
}).catch(function(err) {
 console.log('rejected:' + err); // rejected: 8
});
ログイン後にコピー

Promise.reject()

Promise.reject()和Promise.resolve()正好相反,它接收一个参数值reason,即发生异常的原因。此时返回的Promise对象将会置为rejected态。如下:

var p10 = Promise.reject('手动拒绝');
p10.then(function(data) {
 console.log(data); // 这里不会执行,因为是rejected态
}).catch(function(err) {
 console.log(err); // 手动拒绝
}).then(function(data) {
 // 不受上一级影响
 console.log('状态:fulfilled'); // 状态:fulfilled
});
ログイン後にコピー

总之,除非Promise.then()方法内部抛出异常或者是明确置为rejected态,否则它返回的Promise的状态都是fulfilled态,即完成态,并且它的状态不受它的上一级的状态的影响。

总结

大概常用的方法就写那么多,剩下的看自己实际需要再去了解。

解决Node回调地狱的不止有Promise,还有Generator和ES7提出的Async实现。

相信看了本文案例你已经掌握了方法,更多精彩请关注php中文网其它相关文章!

推荐阅读:

怎样使用Vue实现树形视图数据

如何使用JS求得数组的最小公倍数和最大公约数

以上がES6でのPromiseの使い方を詳しく解説の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

関連ラベル:
ソース:php.cn
このウェブサイトの声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。
人気のチュートリアル
詳細>
最新のダウンロード
詳細>
ウェブエフェクト
公式サイト
サイト素材
フロントエンドテンプレート