JavaScript での Promise の使用

高洛峰
リリース: 2018-05-15 17:35:36
オリジナル
1337 人が閲覧しました

Promise は、非同期タスクのコールバック関数の処理方法を標準化する ES6 の関数で、その機能は jQuery の defferred に似ています。簡単に言うと、Promise オブジェクトのさまざまな状態を通じてさまざまなコールバック関数が呼び出されます。現在、IE8 以下はサポートされていませんが、他のブラウザはサポートされています。

Promise オブジェクトの状態は、保留中から解決済みまたは拒否済みに変換された後も変化しません。

使用手順:

var promise = new Promise(function(resolve, reject) {

 // 异步任务,通过调用resolve(value) 或 reject(error),以改变promise对象的状态;改变状态的方法只能在此调用。

//promise状态改变后,会调用对应的回调方法

});

promise.then(function(value){//resolve时的回调函数,参数由异步的函数传进来})

.catch(function(error){//发生异常时或明确reject()时的回调函数})
ログイン後にコピー

具体的な使用方法:

function getURL(URL) {           //因为promise创建时即执行,所以用工厂函数封装promise对象
  return new Promise(function (resolve, reject) {
    var req = new XMLHttpRequest();
    req.open('GET', URL, true);
    req.onload = function () {
      if (req.status === 200) {
        resolve(req.responseText);
      } else {
        reject(new Error(req.statusText));
      }
    };
    req.onerror = function () {
      reject(new Error(req.statusText));
    };
    req.send();
  });
}
// 运行示例
var URL = "http://httpbin.org/get";
getURL(URL).then(function onFulfilled(value){
  console.log(value);
}).catch(function onRejected(error){
  console.error(error);
})
ログイン後にコピー

Promise のコールバックは非同期のみであり、同期タスクのコールバックも非同期で実行されます。

var promise = new Promise(function (resolve){
  console.log("inner promise");         // 执行1:同步任务先执行
  resolve(‘callBack');
});
promise.then(function(value){
  console.log(value);              // 执行3:虽然注册时状态为resolved,但回调仍是异步的;
});
console.log("outer promise");          // 执行2:同步代码先执行
ログイン後にコピー

promiseメソッドチェーン

thenメソッドで登録されたコールバックが順番に呼び出され、各thenメソッド間で戻り値としてパラメータが渡されます。ただし、コールバックで例外が発生すると、then コールバックがスキップされ、catch コールバックが直接呼び出され、その後、残りの then コールバックが呼び出されます。 then(onFulfilled, onRejected) では、onFulfilled 例外は独自の onRejected によってキャッチされないため、最初に catch が使用されます。

Promise .then(taskA) .then(taskB) .catch(onRejected) .then(finalTask​​);

taskA は例外をスローし、taskB はスキップされますが、promise オブジェクトのステータスにより、finalTask​​ は引き続き呼び出されますcatch によって返されたものは解決されます。

then メソッドでは 3 種類の値を返すことができます

1. 次の then メソッドは、ステータスに応じて実行する onFullfilled/onRejected コールバック関数を選択します。パラメータは引き続き resolv によって渡されます。新しい Promise の /reject メソッド

2 。次の then メソッドは現在の Promise オブジェクトの状態を継承し、実際のパラメータは return です。前の then の値; 戻り値がない場合は、デフォルトで未定義が返されます。

3. Throw Exception (同期/非同期): throw new Error('xxx');

その後、コールバック関数を登録するだけでなく、また、コールバック関数の戻り値を変換し、新しい Promise オブジェクトを作成して返します。実際、Promise はメソッド チェーン内の同じ Promise オブジェクトを操作しません。

var aPromise = new Promise(function (resolve) {
  resolve(100);
});
var thenPromise = aPromise.then(function (value) {
  console.log(value);
});
var catchPromise = thenPromise.catch(function (error) {
  console.error(error);
});
console.log(aPromise !== thenPromise); // => true
console.log(thenPromise !== catchPromise);// => true
ログイン後にコピー

Promise.all() 静的メソッドは、複数の非同期タスクを同時に実行します。受信したすべての Promise オブジェクトが FulFilled または Rejected になるまで、後続の処理は続行されません。

Promise.all([promiseA, promiseB]).then(function(results){//results是个数组,元素值和前面promises对象对应});

// 由promise对象组成的数组会同时执行,而不是一个一个顺序执行,开始时间基本相同。
function timerPromisefy(delay) {
  console.log('开始时间:”'+Date.now()) 
  return new Promise(function (resolve) {
    setTimeout(function () {
      resolve(delay);
    }, delay);
  });
}
var startDate = Date.now();
Promise.all([
  timerPromisefy(100),    //promise用工厂形式包装一下
  timerPromisefy(200),
  timerPromisefy(300),
  timerPromisefy(400)
]).then(function (values) {
  console.log(values);  // [100,200,300,400]
});
ログイン後にコピー

同時に実行せず、Promiseを次々に実行します

//promise factories返回promise对象,只有当前异步任务结束时才执行下一个then
function sequentialize(promiseFactories) {
  var chain = Promise.resolve();
  promiseFactories.forEach(function (promiseFactory) {
    chain = chain.then(promiseFactory);
  });
  return chain;
}
ログイン後にコピー

Promise.race()はall()に似ていますが、race()はPromiseオブジェクトがFulFilledに入る限り、対応するコールバックを実行します。または拒否状態関数。ただし、最初の Promise オブジェクトが Fulfilled になった後は、他の Promise オブジェクトの継続的な実行には影響しません。

//沿用Promise.all()的例子
Promise.race([
  timerPromisefy(1),
  timerPromisefy(32),
  timerPromisefy(64),
  timerPromisefy(128)
]).then(function (value) {
  console.log(values);  // [1]
});
ログイン後にコピー

Promise.race() をタイマーとして使用する素晴らしい方法

Promise.race([
  new Promise(function (resolve, reject) {
    setTimeout(reject, 5000);     // timeout after 5 secs
  }),
  doSomethingThatMayTakeAwhile()
]);
ログイン後にコピー

then で Promise の状態を変更します

then のコールバックには値パラメータしかないため、状態を変更するメソッドはありません (コンストラクターの非同期タスクで使用されます)、次に渡される Promise オブジェクトの状態を変更したい場合は、新しい Promise オブジェクトを作成し、非同期タスクで状態を変更するかどうかを決定し、最後に返すことしかできません。それを次の then/catch に渡します。

var promise = Promise.resolve(‘xxx');//创建promise对象的简介方法
promise.then(function (value) {
  var pms=new Promise(function(resolve,reject){
    setTimeout(function () {
      // 在此可以判断是否改变状态reject/resolve
      Reject(‘args');
    }, 1000);
  })
  return pms;  //该promise对象可以具有新状态,下一个then/catch需要等异步结束才会执行回调;如果返回普通值/undefined,之后的then/catch会立即执行
}).catch(function (error) {
  // 被reject时调用
  console.log(error)
});
ログイン後にコピー

2 つの Promise の結果を取得します

//方法1:通过在外层的变量传递
var user;
getUserByName('nolan').then(function (result) {
  user = result;
  return getUserAccountById(user.id);
}).then(function (userAccount) {
  //可以访问user和userAccount
});

//方法2:后一个then方法提到前一个回调中
getUserByName('nolan').then(function (user) {
  return getUserAccountById(user.id).then(function (userAccount) {
    //可以访问user和userAccount
  });
});
ログイン後にコピー

Promise を使用するときは全体の構造に注意してください

doSomething() と doSomethingElse() の両方が Promise オブジェクトを返すと仮定します

一般的な方法:

doSomething().then(doSomethingElse).then(finalHandler);
doSomething
|-----------------|
         doSomethingElse(resultOfDoSomething)  //返回新promise,下一个then要收到新状态才执行
         |------------------|
                   finalHandler(resultOfDoSomethingElse)
                   |---------------------|
ログイン後にコピー

一般的な回避策:

doSomething().then(function () { return doSomethingElse();}).then(finalHandler);
doSomething
|-----------------|
         doSomethingElse(undefined) //then外层函数的arguments[0]== resultOfDoSomething
         |------------------|
                   finalHandler(resultOfDoSomethingElse)
                   |------------------|
ログイン後にコピー

エラー方法 1:

doSomething().then(function () { doSomethingElse();}).then(finalHandler);
doSomething
|-----------------|
         doSomethingElse(undefined)  //虽然doSomethingElse会返回promise对象,但最外层的回调函数是return undefined,所以下一个then方法无需等待新promise的状态,会马上执行回调。
         |------------------|
         finalHandler(undefined)
         |------------------|
ログイン後にコピー

間違った方法 2:

doSomething().then(doSomethingElse()).then(finalHandler);
doSomething
|-----------------|
doSomethingElse(undefined)     //回调函数在注册时就直接被调用
|----------|
         finalHandler(resultOfDoSomething)
         |------------------|
ログイン後にコピー

JavaScript での Promise の使用に関するその他の記事については、PHP 中国語 Web サイトに注目してください。

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