JS非同期プログラミングPromise

前言

「JS非同期プログラミングコールバック」の記事「JSはシングルスレッドイベントループに基づいている」という概念、コールバック関数はすぐには実行されない、イベントが実行されたかどうかを検出するイベントポーリング結果をコールバック関数のパラメータに入れてから、コールバック関数を実行待ちのイベントキューに追加します。

コールバック関数についても話しました:

非同期コールバック関数の特性のために、最初の “コールバック地獄”です:コールバック関数は非同期関数のパラメータです、入れ子になった層ごとに、あまりにも多くのネスティング、コードロジックは混乱し、エラーキャプチャを行うことはできませんそして処理(コールバック関数の中だけでcatchを試してください)。

第二に、コールバックの実装は自然言語の線形思考に準拠しておらず、理解するのは容易ではありません。

非同期関数が他の人によって提供されたライブラリである場合、コールバック関数をそれに渡しますが、非同期関数がコールバック関数を呼び出すこと以外に何をするのかを知ることはできません。

func1(() => {
    func2(() => {
        func3(() => {
            func4(() => {
                try {
                    ...
                } catch (err){
                    ...
                }
            })
        });
    });
});

一、Promise 原理

まず、Promiseは「コミットメント」と言い換えられ、JavaScriptの対象であり、成功したかどうかにかかわらず、その約束が最終的に結果を返すことを示します。

Promiseには3つの状態があります:保留中、満杯、および拒否約束はアトミックになるように設計されています状態が保留状態から満杯状態または拒否状態に遷移すると、変更することはできません。

var promise1 = new Promise((resolve, reject) => {
    console.log("Promise 构造器会立即执行");
    setTimeout(function (){
        if(true) {
            resolve("完成");
        } else {
            reject("失败");
        }
    }, 1000);
})
promise1
.then((result) => {
    // do something
    console.log(result);
    return 1
    
    // return Promise.resolve(1);  // 返回一个决议为成功的 promise 实例
    // return Promise.reject("error");  // 返回一个决议为拒绝的 Promise 实例
})
.then((result) => {
    // .then() 方法会返回一个 promise, 完成调用的参数为前一个 promise 的返回值或者决议值。
    // do other things
    console.log(result);
    throw new Error("错误")  // 抛出错误是隐式拒绝
})
.catch((error) => {
    // 捕捉错误
    console.log(error)
})
.then(() => {
    // 还能继续执行!
})
.finally(() => {
    // always do somethings
    console.log("finally!")
})

二、Promise 的优势

  1. 連鎖呼び出し
    また、Promiseはthenメソッドを使用して新しいPromiseオブジェクトを返します。これにより、状態データを渡すことができます。一方、連鎖書き込みは同期書き込みに近く、より線形です。

  2. キャッチエラー
    外部で捕捉できないコールバック関数エラーの問題と比較して、Promiseは一連の非同期呼び出しのエラー処理を提供します。

  3. コントロール反転と反転
    サードパーティが提供する非同期関数のため、コールバック関数が実行されるという保証はありませんが、Promiseの機能は非同期関数が1回しか解決されないことを保証でき、コードは常に非同期に実行されます。

  4. Promise.allとPromise.raceは、Promiseの常に未解決の並列Promiseネスト問題を解決するために使用できます。

三、Promise 的不足

  1. .then()はそれぞれ独立した範囲です

    複数の.then()メソッドを追加すると、多数の独立したスコープが作成され、関数スコープのクロージャの層を外側にラップすることによってのみ状態データが共有されます。

  2. 単一の.then()をキャンセルできません
    Promiseチェーンの.then()メソッドのいずれかにステートメント実行エラーがある場合、catchメソッドのエラー処理にもかかわらず、Promiseチェーン全体の実行が中断されることはありません。

  3. 進捗状況がわからない
    Promiseは保留状態から満杯または拒否状態までしかできないため、保留フェーズの進行状況はわかりません。

四、Promise 应用

// Promise 封装 ajax
function fetch(method, url, data){
    return new Promise((resolve, reject) => {
        var xhr = new XMLHttpRequest();
        var method = method || "GET";
        var data = data || null;
        xhr.open(method, url, true);
        xhr.onreadystatechange = function() {
            if(xhr.status === 200 && xhr.readyState === 4){
                resolve(xhr.responseText);
            } else {
                reject(xhr.responseText);
            }
        }
        xhr.send(data);
        })
}

// 使用
fetch("GET", "/some/url.json", null)
.then(result => {
    console.log(result);
})

// 封装 nodejs error first 风格回调
function readFile(url) {
    return new Promise((resolve, reject) => {
       fs.readFile(url,'utf8', (err, data) => {
        if(err) {
            reject(err);
            return;
        }
        resolve(data)
        }) 
    })
}

五、总结

Promiseは、ES6によって提案された、非同期タスクの完了ステータスを強調するアトミックな、簡素化された非同期プロセス制御のための新しい仕様です。これにより、コードの追跡と保守が容易になります。 Promiseはイベントポーリングの非同期イベントキュー内のマイクロタスクに属し、マイクロタスクは常に一斉に実行され、マクロタスクはラウンドごとに1回実行されます。 》。

2019/02/24 @Manncoffee

元のリンク