ホームページ ウェブフロントエンド jsチュートリアル Node.jsの非同期フロー制御を詳しく説明

Node.jsの非同期フロー制御を詳しく説明

Jan 22, 2018 am 10:11 AM
javascript node.js 詳しい説明

関数コールバックの使用に関する深い経験がない場合、これらの内容を読むのはまだ少し難しいです。 Node.js の独特な非同期特性により、「コールバック地獄」の問題が発生しました。この記事では、非同期フローの問題を解決する方法を詳しく記録しました。この記事では主に Node.js の非同期フロー制御について紹介していますが、編集者が非常に優れていると感じたので、参考として共有します。編集者をフォローして見てみましょう。皆さんのお役に立てれば幸いです。

記事が長くなりますので、この記事は非同期ストリーミングモードについての説明です。この記事では、単純な Web スパイダーの例を使用します。その機能は、指定された URL の Web ページ コンテンツをクロールし、それをプロジェクトに保存することです。記事全体のソース コード デモが表示されます。

1. ネイティブ JavaScript モード

この記事は初心者向けではないため、基本的な内容のほとんどは省略されます:

(spider_v1.js)


const request = require("request");
const fs = require("fs");
const mkdirp = require("mkdirp");
const path = require("path");
const utilities = require("./utilities");

function spider(url, callback) {
  const filename = utilities.urlToFilename(url);
  console.log(`filename: ${filename}`);

  fs.exists(filename, exists => {
    if (!exists) {
      console.log(`Downloading ${url}`);

      request(url, (err, response, body) => {
        if (err) {
          callback(err);
        } else {
          mkdirp(path.dirname(filename), err => {
            if (err) {
              callback(err);
            } else {
              fs.writeFile(filename, body, err => {
                if (err) {
                  callback(err);
                } else {
                  callback(null, filename, true);
                }
              });
            }
          });
        }
      });
    } else {
      callback(null, filename, false);
    }
  });
}

spider(process.argv[2], (err, filename, downloaded) => {
  if (err) {
    console.log(err);
  } else if (downloaded) {
    console.log(`Completed the download of ${filename}`);
  } else {
    console.log(`${filename} was already downloaded`);
  }
});
ログイン後にコピー

上記のコードの流れはおそらく次のとおりです。次のように:

  1. URL をファイル名に変換します

  2. ファイル名が存在するかどうかを確認し、存在する場合は直接戻り、そうでない場合は次のステップに進みます

  3. リクエストを送信して本文を取得します

  4. ファイル内に本文を書き込みます

これは、1 つの URL のコンテンツのみをクロールできるスパイダーです。上記のコールバックがどれほど面倒かを見てください。次に、最適化を開始します。

まず、if else メソッドを最適化できます。言うまでもなく、比較効果は次のとおりです。ネストされていますが、経験豊富なプログラマは、この書き方ではエラーが強調されすぎると考えるかもしれません。読みやすさの観点からも、このような要件がプログラミングの焦点にあるはずです。

もう 1 つの最適化は、上記のコードのスパイダー関数で、ダウンロードされたファイルと保存されたファイルを分割することができます。

(spider_v2.js)

/// before
if (err) {
  callback(err);
} else {
  callback(null, filename, true);
}

/// after
if (err) {
  return callback(err);
}
callback(null, filename, true);
ログイン後にコピー

上記のコードは基本的にネイティブ最適化の結果ですが、このスパイダーの機能は単純すぎるため、特定の Web ページ内のすべての URL をクロールする必要があります。シリアルおよびパラレルの問題が発生します。

(spider_v3.js)

const request = require("request");
const fs = require("fs");
const mkdirp = require("mkdirp");
const path = require("path");
const utilities = require("./utilities");

function saveFile(filename, contents, callback) {
  mkdirp(path.dirname(filename), err => {
    if (err) {
      return callback(err);
    }
    fs.writeFile(filename, contents, callback);
  });
}

function download(url, filename, callback) {
  console.log(`Downloading ${url}`);

  request(url, (err, response, body) => {
    if (err) {
      return callback(err);
    }
    saveFile(filename, body, err => {
      if (err) {
        return callback(err);
      }
      console.log(`Downloaded and saved: ${url}`);
      callback(null, body);
    });
  })
}

function spider(url, callback) {
  const filename = utilities.urlToFilename(url);
  console.log(`filename: ${filename}`);

  fs.exists(filename, exists => {
    if (exists) {
      return callback(null, filename, false);
    }
    download(url, filename, err => {
      if (err) {
        return callback(err);
      }
      callback(null, filename, true);
    })
  });
}

spider(process.argv[2], (err, filename, downloaded) => {
  if (err) {
    console.log(err);
  } else if (downloaded) {
    console.log(`Completed the download of ${filename}`);
  } else {
    console.log(`${filename} was already downloaded`);
  }
});
ログイン後にコピー

前のコードと比較すると、上記のコードにはさらに 2 つのコア関数があります。 1 つ目は、補助クラスを通じて特定の本体内のリンクを取得することです:


const request = require("request");
const fs = require("fs");
const mkdirp = require("mkdirp");
const path = require("path");
const utilities = require("./utilities");

function saveFile(filename, contents, callback) {
  mkdirp(path.dirname(filename), err => {
    if (err) {
      return callback(err);
    }
    fs.writeFile(filename, contents, callback);
  });
}

function download(url, filename, callback) {
  console.log(`Downloading ${url}`);

  request(url, (err, response, body) => {
    if (err) {
      return callback(err);
    }
    saveFile(filename, body, err => {
      if (err) {
        return callback(err);
      }
      console.log(`Downloaded and saved: ${url}`);
      callback(null, body);
    });
  })
}

/// 最大的启发是实现了如何异步循环遍历数组
function spiderLinks(currentUrl, body, nesting, callback) {
  if (nesting === 0) {
    return process.nextTick(callback);
  }

  const links = utilities.getPageLinks(currentUrl, body);

  function iterate(index) {
    if (index === links.length) {
      return callback();
    }
    spider(links[index], nesting - 1, err => {
      if (err) {
        return callback(err);
      }
      iterate((index + 1));
    })
  }

  iterate(0);
}

function spider(url, nesting, callback) {
  const filename = utilities.urlToFilename(url);

  fs.readFile(filename, "utf8", (err, body) => {
    if (err) {
      if (err.code !== 'ENOENT') {
        return callback(err);
      }
      return download(url, filename, (err, body) => {
        if (err) {
          return callback(err);
        }
        spiderLinks(url, body, nesting, callback);
      });
    }

    spiderLinks(url, body, nesting, callback);
  });
}

spider(process.argv[2], 2, (err, filename, downloaded) => {
  if (err) {
    console.log(err);
  } else if (downloaded) {
    console.log(`Completed the download of ${filename}`);
  } else {
    console.log(`${filename} was already downloaded`);
  }
});
ログイン後にコピー

。内部実装 説明はしませんが、他のコア コードは次のとおりです:


const links = utilities.getPageLinks(currentUrl, body);
ログイン後にコピー

上記の小さなコードは、非同期シリアル化を実装するためのネイティブ パターンであると言えます。これらに加えて、この属性を通じてネストの概念も導入され、クロール レベルを制御できます。

この時点でシリアル機能は完全に実装されました。パフォーマンスを考慮して、並列クローリング機能を開発する必要があります。

(spider_v4.js)

/// 最大的启发是实现了如何异步循环遍历数组
function spiderLinks(currentUrl, body, nesting, callback) {
  if (nesting === 0) {
    return process.nextTick(callback);
  }

  const links = utilities.getPageLinks(currentUrl, body);

  function iterate(index) {
    if (index === links.length) {
      return callback();
    }
    spider(links[index], nesting - 1, err => {
      if (err) {
        return callback(err);
      }
      iterate((index + 1));
    })
  }

  iterate(0);
}
ログイン後にコピー

このコードも非常にシンプルで、2 つの主要な内容があります。 1 つは、同時実行を実現する方法です。


const request = require("request");
const fs = require("fs");
const mkdirp = require("mkdirp");
const path = require("path");
const utilities = require("./utilities");

function saveFile(filename, contents, callback) {
  mkdirp(path.dirname(filename), err => {
    if (err) {
      return callback(err);
    }
    fs.writeFile(filename, contents, callback);
  });
}

function download(url, filename, callback) {
  console.log(`Downloading ${url}`);

  request(url, (err, response, body) => {
    if (err) {
      return callback(err);
    }
    saveFile(filename, body, err => {
      if (err) {
        return callback(err);
      }
      console.log(`Downloaded and saved: ${url}`);
      callback(null, body);
    });
  })
}

/// 最大的启发是实现了如何异步循环遍历数组
function spiderLinks(currentUrl, body, nesting, callback) {
  if (nesting === 0) {
    return process.nextTick(callback);
  }

  const links = utilities.getPageLinks(currentUrl, body);
  if (links.length === 0) {
    return process.nextTick(callback);
  }

  let completed = 0, hasErrors = false;

  function done(err) {
    if (err) {
      hasErrors = true;
      return callback(err);
    }

    if (++completed === links.length && !hasErrors) {
      return callback();
    }
  }

  links.forEach(link => {
    spider(link, nesting - 1, done);
  });
}

const spidering = new Map();

function spider(url, nesting, callback) {
  if (spidering.has(url)) {
    return process.nextTick(callback);
  }

  spidering.set(url, true);

  const filename = utilities.urlToFilename(url);

  /// In this pattern, there will be some issues.
  /// Possible problems to download the same url again and again。
  fs.readFile(filename, "utf8", (err, body) => {
    if (err) {
      if (err.code !== 'ENOENT') {
        return callback(err);
      }
      return download(url, filename, (err, body) => {
        if (err) {
          return callback(err);
        }
        spiderLinks(url, body, nesting, callback);
      });
    }

    spiderLinks(url, body, nesting, callback);
  });
}

spider(process.argv[2], 2, (err, filename, downloaded) => {
  if (err) {
    console.log(err);
  } else if (downloaded) {
    console.log(`Completed the download of ${filename}`);
  } else {
    console.log(`${filename} was already downloaded`);
  }
});
ログイン後にコピー

上記のコードは、同時実行を実現するためのパターンであると言えます。これはループトラバーサルを使用して実現されます。もう 1 つの核心は、同時実行であるため、fs.exists を使用すると問題が発生し、同じファイルが繰り返しダウンロードされる可能性があるということです。解決策は次のとおりです。


Map を使用して特定の URL をキャッシュします。その URL は次のようになります。キーとして使用されます

  • ここで、同時実行の最大数を制限するという新しい要件があるため、ここで最も重要だと思われる概念であるキューを紹介します。

    (task-Queue.js)

/// 最大的启发是实现了如何异步循环遍历数组
function spiderLinks(currentUrl, body, nesting, callback) {
  if (nesting === 0) {
    return process.nextTick(callback);
  }

  const links = utilities.getPageLinks(currentUrl, body);
  if (links.length === 0) {
    return process.nextTick(callback);
  }

  let completed = 0, hasErrors = false;

  function done(err) {
    if (err) {
      hasErrors = true;
      return callback(err);
    }

    if (++completed === links.length && !hasErrors) {
      return callback();
    }
  }

  links.forEach(link => {
    spider(link, nesting - 1, done);
  });
}
ログイン後にコピー

上記のコードはキューの実装コードであり、タスクがキューに追加されるときにコアとなることがわかります。これは、タスクをすぐに実行する必要があるという意味ではなく、next がすぐに呼び出されるという意味です。

(spider_v5.js)

class TaskQueue {
  constructor(concurrency) {
    this.concurrency = concurrency;
    this.running = 0;
    this.queue = [];
  }

  pushTask(task) {
    this.queue.push(task);
    this.next();
  }

  next() {
    while (this.running < this.concurrency && this.queue.length) {
      const task = this.queue.shift();
      task(() => {
        this.running--;
        this.next();
      });
      this.running++;
    }
  }
}

module.exports = TaskQueue;
ログイン後にコピー

したがって、同時実行数を制限するには、タスクトラバーサルを SpiderLinks メソッドのキューに入れるだけです。これは比較的簡単です。

これまで、ネイティブ JavaScript を使用して、比較的完全な機能を備えた Web スパイダーを実装してきました。この関数は、シリアルおよび同時実行の両方が可能で、同時実行数も制御できます。

2. async ライブラリを使用する

さまざまな関数を別の関数に配置すると、大きなメリットが得られます。async ライブラリは非常に人気があり、内部的にはコールバックに基づいています。

(spider_v6.js)

const request = require("request");
const fs = require("fs");
const mkdirp = require("mkdirp");
const path = require("path");
const utilities = require("./utilities");
const TaskQueue = require("./task-Queue");
const downloadQueue = new TaskQueue(2);

function saveFile(filename, contents, callback) {
  mkdirp(path.dirname(filename), err => {
    if (err) {
      return callback(err);
    }
    fs.writeFile(filename, contents, callback);
  });
}

function download(url, filename, callback) {
  console.log(`Downloading ${url}`);

  request(url, (err, response, body) => {
    if (err) {
      return callback(err);
    }
    saveFile(filename, body, err => {
      if (err) {
        return callback(err);
      }
      console.log(`Downloaded and saved: ${url}`);
      callback(null, body);
    });
  })
}

/// 最大的启发是实现了如何异步循环遍历数组
function spiderLinks(currentUrl, body, nesting, callback) {
  if (nesting === 0) {
    return process.nextTick(callback);
  }

  const links = utilities.getPageLinks(currentUrl, body);
  if (links.length === 0) {
    return process.nextTick(callback);
  }

  let completed = 0, hasErrors = false;

  links.forEach(link => {
    /// 给队列出传递一个任务,这个任务首先是一个函数,其次该函数接受一个参数
    /// 当调用任务时,触发该函数,然后给函数传递一个参数,告诉该函数在任务结束时干什么
    downloadQueue.pushTask(done => {
      spider(link, nesting - 1, err => {
        /// 这里表示,只要发生错误,队列就会退出
        if (err) {
          hasErrors = true;
          return callback(err);
        }
        if (++completed === links.length && !hasErrors) {
          callback();
        }

        done();
      });
    });

  });
}

const spidering = new Map();

function spider(url, nesting, callback) {
  if (spidering.has(url)) {
    return process.nextTick(callback);
  }

  spidering.set(url, true);

  const filename = utilities.urlToFilename(url);

  /// In this pattern, there will be some issues.
  /// Possible problems to download the same url again and again。
  fs.readFile(filename, "utf8", (err, body) => {
    if (err) {
      if (err.code !== &#39;ENOENT&#39;) {
        return callback(err);
      }
      return download(url, filename, (err, body) => {
        if (err) {
          return callback(err);
        }
        spiderLinks(url, body, nesting, callback);
      });
    }

    spiderLinks(url, body, nesting, callback);
  });
}

spider(process.argv[2], 2, (err, filename, downloaded) => {
  if (err) {
    console.log(`error: ${err}`);
  } else if (downloaded) {
    console.log(`Completed the download of ${filename}`);
  } else {
    console.log(`${filename} was already downloaded`);
  }
});
ログイン後にコピー

上記のコードでは、async の関数は 3 つだけ使用しました:


const request = require("request");
const fs = require("fs");
const mkdirp = require("mkdirp");
const path = require("path");
const utilities = require("./utilities");
const series = require("async/series");
const eachSeries = require("async/eachSeries");

function download(url, filename, callback) {
  console.log(`Downloading ${url}`);

  let body;

  series([
    callback => {
      request(url, (err, response, resBody) => {
        if (err) {
          return callback(err);
        }
        body = resBody;
        callback();
      });
    },
    mkdirp.bind(null, path.dirname(filename)),
    callback => {
      fs.writeFile(filename, body, callback);
    }
  ], err => {
    if (err) {
      return callback(err);
    }
    console.log(`Downloaded and saved: ${url}`);
    callback(null, body);
  });
}

/// 最大的启发是实现了如何异步循环遍历数组
function spiderLinks(currentUrl, body, nesting, callback) {
  if (nesting === 0) {
    return process.nextTick(callback);
  }

  const links = utilities.getPageLinks(currentUrl, body);
  if (links.length === 0) {
    return process.nextTick(callback);
  }

  eachSeries(links, (link, cb) => {
    "use strict";
    spider(link, nesting - 1, cb);
  }, callback);
}

const spidering = new Map();

function spider(url, nesting, callback) {
  if (spidering.has(url)) {
    return process.nextTick(callback);
  }

  spidering.set(url, true);

  const filename = utilities.urlToFilename(url);

  fs.readFile(filename, "utf8", (err, body) => {
    if (err) {
      if (err.code !== &#39;ENOENT&#39;) {
        return callback(err);
      }
      return download(url, filename, (err, body) => {
        if (err) {
          return callback(err);
        }
        spiderLinks(url, body, nesting, callback);
      });
    }

    spiderLinks(url, body, nesting, callback);
  });
}

spider(process.argv[2], 1, (err, filename, downloaded) => {
  if (err) {
    console.log(err);
  } else if (downloaded) {
    console.log(`Completed the download of ${filename}`);
  } else {
    console.log(`${filename} was already downloaded`);
  }
});
ログイン後にコピー

比較的簡単なので説明は省略します。非同期のキューのコードは (spider_v7.js) にあります。これは上記のカスタム キューとよく似ているため、これ以上の説明は省略します。


3.Promise

Promise は、このプロトコルを実装するライブラリが多数あります。簡単に言うと、Promise は合意です。完了すると、その解決メソッドが呼び出され、失敗すると、その拒否メソッドが呼び出されます。 then メソッドを実装してから、Promise 自体を返し、呼び出しチェーンを形成します。

其实Promise的内容有很多,在实际应用中是如何把普通的函数promise化。这方面的内容在这里也不讲了,我自己也不够格

(spider_v8.js)


const utilities = require("./utilities");
const request = utilities.promisify(require("request"));
const fs = require("fs");
const readFile = utilities.promisify(fs.readFile);
const writeFile = utilities.promisify(fs.writeFile);
const mkdirp = utilities.promisify(require("mkdirp"));
const path = require("path");


function saveFile(filename, contents, callback) {
  mkdirp(path.dirname(filename), err => {
    if (err) {
      return callback(err);
    }
    fs.writeFile(filename, contents, callback);
  });
}

function download(url, filename) {
  console.log(`Downloading ${url}`);

  let body;

  return request(url)
    .then(response => {
      "use strict";
      body = response.body;
      return mkdirp(path.dirname(filename));
    })
    .then(() => writeFile(filename, body))
    .then(() => {
      "use strict";
      console.log(`Downloaded adn saved: ${url}`);
      return body;
    });
}

/// promise编程的本质就是为了解决在函数中设置回调函数的问题
/// 通过中间层promise来实现异步函数同步化
function spiderLinks(currentUrl, body, nesting) {
  let promise = Promise.resolve();
  if (nesting === 0) {
    return promise;
  }

  const links = utilities.getPageLinks(currentUrl, body);

  links.forEach(link => {
    "use strict";
    promise = promise.then(() => spider(link, nesting - 1));
  });

  return promise;
}

function spider(url, nesting) {
  const filename = utilities.urlToFilename(url);

  return readFile(filename, "utf8")
    .then(
      body => spiderLinks(url, body, nesting),
      err => {
        "use strict";
        if (err.code !== &#39;ENOENT&#39;) {
          /// 抛出错误,这个方便与在整个异步链的最后通过呢catch来捕获这个链中的错误
          throw err;
        }
        return download(url, filename)
          .then(body => spiderLinks(url, body, nesting));
      }
    );
}

spider(process.argv[2], 1)
  .then(() => {
    "use strict";
    console.log(&#39;Download complete&#39;);
  })
  .catch(err => {
    "use strict";
    console.log(err);
  });
ログイン後にコピー

可以看到上边的代码中的函数都是没有callback的,只需要在最后catch就可以了。

在设计api的时候,应该支持两种方式,及支持callback,又支持promise


function asyncpision(pidend, pisor, cb) {
  return new Promise((resolve, reject) => {
    "use strict";
    process.nextTick(() => {
      const result = pidend / pisor;
      if (isNaN(result) || !Number.isFinite(result)) {
        const error = new Error("Invalid operands");
        if (cb) {
          cb(error);
        }
        return reject(error);
      }

      if (cb) {
        cb(null, result);
      }
      resolve(result);
    });
  });
}

asyncpision(10, 2, (err, result) => {
  "use strict";
  if (err) {
    return console.log(err);
  }
  console.log(result);
});

asyncpision(22, 11)
  .then((result) => console.log(result))
  .catch((err) => console.log(err));
ログイン後にコピー

4.Generator

Generator很有意思,他可以让暂停函数和恢复函数,利用thunkify和co这两个库,我们下边的代码实现起来非常酷。

(spider_v9.js)


const thunkify = require("thunkify");
const co = require("co");
const path = require("path");
const utilities = require("./utilities");

const request = thunkify(require("request"));
const fs = require("fs");
const mkdirp = thunkify(require("mkdirp"));
const readFile = thunkify(fs.readFile);
const writeFile = thunkify(fs.writeFile);
const nextTick = thunkify(process.nextTick);

function* download(url, filename) {
  console.log(`Downloading ${url}`);

  const response = yield request(url);
  console.log(response);

  const body = response[1];
  yield mkdirp(path.dirname(filename));

  yield writeFile(filename, body);

  console.log(`Downloaded and saved ${url}`);
  return body;
}

function* spider(url, nesting) {
  const filename = utilities.urlToFilename(url);

  let body;

  try {
    body = yield readFile(filename, "utf8");
  } catch (err) {
    if (err.code !== &#39;ENOENT&#39;) {
      throw err;
    }
    body = yield download(url, filename);
  }

  yield spiderLinks(url, body, nesting);
}

function* spiderLinks(currentUrl, body, nesting) {
  if (nesting === 0) {
    return nextTick();
  }

  const links = utilities.getPageLinks(currentUrl, body);

  for (let i = 0; i < links.length; i++) {
    yield spider(links[i], nesting - 1);
  }
}

/// 通过co就自动处理了回调函数,直接返回了回调函数中的参数,把这些参数放到一个数组中,但是去掉了err信息
co(function* () {
  try {
    yield spider(process.argv[2], 1);
    console.log(&#39;Download complete&#39;);
  } catch (err) {
    console.log(err);
  }
});
ログイン後にコピー

总结

我并没有写promise和generator并发的代码。以上这些内容来自于这本书nodejs-design-patterns 。

相关推荐:

Node.js之关于异步流控制的简单介绍

微信小程序中Promise进行异步流程处理的实现过程

小程序开发之利用co处理异步流程的实例教程

以上がNode.jsの非同期フロー制御を詳しく説明の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

このウェブサイトの声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。

ホットAIツール

Undresser.AI Undress

Undresser.AI Undress

リアルなヌード写真を作成する AI 搭載アプリ

AI Clothes Remover

AI Clothes Remover

写真から衣服を削除するオンライン AI ツール。

Undress AI Tool

Undress AI Tool

脱衣画像を無料で

Clothoff.io

Clothoff.io

AI衣類リムーバー

AI Hentai Generator

AI Hentai Generator

AIヘンタイを無料で生成します。

ホットツール

メモ帳++7.3.1

メモ帳++7.3.1

使いやすく無料のコードエディター

SublimeText3 中国語版

SublimeText3 中国語版

中国語版、とても使いやすい

ゼンドスタジオ 13.0.1

ゼンドスタジオ 13.0.1

強力な PHP 統合開発環境

ドリームウィーバー CS6

ドリームウィーバー CS6

ビジュアル Web 開発ツール

SublimeText3 Mac版

SublimeText3 Mac版

神レベルのコード編集ソフト(SublimeText3)

Win11での管理者権限の取得について詳しく解説 Win11での管理者権限の取得について詳しく解説 Mar 08, 2024 pm 03:06 PM

Windows オペレーティング システムは世界で最も人気のあるオペレーティング システムの 1 つであり、その新バージョン Win11 が大きな注目を集めています。 Win11 システムでは、管理者権限の取得は重要な操作であり、管理者権限を取得すると、ユーザーはシステム上でより多くの操作や設定を実行できるようになります。この記事では、Win11システムで管理者権限を取得する方法と、権限を効果的に管理する方法を詳しく紹介します。 Win11 システムでは、管理者権限はローカル管理者とドメイン管理者の 2 種類に分かれています。ローカル管理者はローカル コンピュータに対する完全な管理権限を持っています

Oracle SQLの除算演算の詳細説明 Oracle SQLの除算演算の詳細説明 Mar 10, 2024 am 09:51 AM

OracleSQL の除算演算の詳細な説明 OracleSQL では、除算演算は一般的かつ重要な数学演算であり、2 つの数値を除算した結果を計算するために使用されます。除算はデータベース問合せでよく使用されるため、OracleSQL での除算演算とその使用法を理解することは、データベース開発者にとって重要なスキルの 1 つです。この記事では、OracleSQL の除算演算に関する関連知識を詳細に説明し、読者の参考となる具体的なコード例を示します。 1. OracleSQL での除算演算

PHPモジュロ演算子の役割と使い方を詳しく解説 PHPモジュロ演算子の役割と使い方を詳しく解説 Mar 19, 2024 pm 04:33 PM

PHP のモジュロ演算子 (%) は、2 つの数値を除算した余りを取得するために使用されます。この記事では、モジュロ演算子の役割と使用法について詳しく説明し、読者の理解を深めるために具体的なコード例を示します。 1. モジュロ演算子の役割 数学では、整数を別の整数で割ると、商と余りが得られます。たとえば、10 を 3 で割ると、商は 3 になり、余りは 1 になります。モジュロ演算子は、この剰余を取得するために使用されます。 2. モジュロ演算子の使用法 PHP では、% 記号を使用してモジュロを表します。

Linuxシステムコールsystem()関数の詳細説明 Linuxシステムコールsystem()関数の詳細説明 Feb 22, 2024 pm 08:21 PM

Linux システム コール system() 関数の詳細説明 システム コールは、Linux オペレーティング システムの非常に重要な部分であり、システム カーネルと対話する方法を提供します。その中でも、system()関数はよく使われるシステムコール関数の一つです。この記事では、system() 関数の使用法を詳しく紹介し、対応するコード例を示します。システム コールの基本概念 システム コールは、ユーザー プログラムがオペレーティング システム カーネルと対話する方法です。ユーザープログラムはシステムコール関数を呼び出してオペレーティングシステムを要求します。

簡単な JavaScript チュートリアル: HTTP ステータス コードを取得する方法 簡単な JavaScript チュートリアル: HTTP ステータス コードを取得する方法 Jan 05, 2024 pm 06:08 PM

JavaScript チュートリアル: HTTP ステータス コードを取得する方法、特定のコード例が必要です 序文: Web 開発では、サーバーとのデータ対話が頻繁に発生します。サーバーと通信するとき、多くの場合、返された HTTP ステータス コードを取得して操作が成功したかどうかを判断し、さまざまなステータス コードに基づいて対応する処理を実行する必要があります。この記事では、JavaScript を使用して HTTP ステータス コードを取得する方法を説明し、いくつかの実用的なコード例を示します。 XMLHttpRequestの使用

Linuxのcurlコマンドの詳しい説明 Linuxのcurlコマンドの詳しい説明 Feb 21, 2024 pm 10:33 PM

Linuxのcurlコマンドの詳細な説明 要約:curlは、サーバーとのデータ通信に使用される強力なコマンドラインツールです。この記事では、curl コマンドの基本的な使用法を紹介し、読者がコマンドをよりよく理解して適用できるように実際のコード例を示します。 1.カールとは何ですか? curl は、さまざまなネットワーク要求を送受信するために使用されるコマンド ライン ツールです。 HTTP、FTP、TELNETなどの複数のプロトコルをサポートし、ファイルアップロード、ファイルダウンロード、データ送信、プロキシなどの豊富な機能を提供します。

C言語学習ルートを詳細に分析 C言語学習ルートを詳細に分析 Feb 18, 2024 am 10:38 AM

ソフトウェア開発の分野で広く使用されているプログラミング言語として、C 言語は多くの初心者プログラマーにとって最初の選択肢です。 C言語を学ぶと、プログラミングの基礎知識を定着させるだけでなく、問題解決能力や思考力も向上します。この記事では、初心者が学習プロセスをより適切に計画できるようにするための C 言語学習ロードマップを詳しく紹介します。 1. 基本的な文法を学ぶ C 言語の学習を始める前に、まず C 言語の基本的な文法規則を理解する必要があります。これには、変数とデータ型、演算子、制御ステートメント (if ステートメント、

Promise.resolve() について詳しく見る Promise.resolve() について詳しく見る Feb 18, 2024 pm 07:13 PM

Promise.resolve() の詳細な説明には、特定のコード例が必要です。Promise は、非同期操作を処理するための JavaScript のメカニズムです。実際の開発では、順番に実行する必要があるいくつかの非同期タスクを処理する必要があることがよくあり、満たされた Promise オブジェクトを返すために Promise.resolve() メソッドが使用されます。 Promise.resolve() は Promise クラスの静的メソッドであり、

See all articles